1

I'm working on template MyTemplate that is going to be used in following way:

using Alias = MyTemplate<std::pair<int, char>,
                         std::pair<int, double>,
                         std::pair<int, unsigned int>>;

For now we can assume that MyTemplate will take only list of pair types. Moreover, all pair types should have the same first type and second type have to vary.

I want to "catch" the pairs' first_type in MyTemplate. I came up with following definition:

template<typename... Ts>
struct MyTemplate
{
   using first_type = std::decay_t<decltype((Ts::first_type, ...))>;
   // ...
};

When I use typename MyTemplate::first_type in context of different template everything works fine. I only get a warning:

warning: left operand of comma operator has no effect [-Wunused-value]
    using first_type = std::decay_t<decltype((Ts::first_type, ...))>;
                                                                    ^

However, I cannot create instance of Alias because I get that error:

error: missing 'typename' prior to dependent type name 'std::pair<int, char>::first_type'

Do you gave any idea for "generic" solution? I can use C+17.

max66
  • 65,235
  • 10
  • 71
  • 111
Goofy
  • 5,187
  • 5
  • 40
  • 56
  • 1
    `std::decay_t` doesn't make sense. You use a `,` fold expression, but with a type as an operand? – HolyBlackCat Jan 25 '19 at 23:55
  • It's unclear what you actually want the behavior to be. What is `first_type` supposed to be? You have lots of pairs - what's the actual function you're trying to implement – Barry Jan 25 '19 at 23:56
  • The problem is with the "create instance" part, and not with the definition of the templates shown above (although that also has problems of its own). And since the "create instance" part is not shown, the question cannot be answered, but it's most likely [a duplicate of this one](https://stackoverflow.com/questions/7923369/when-is-the-typename-keyword-necessary), or [of this one](https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords). – Sam Varshavchik Jan 25 '19 at 23:57
  • 1
    Also, is there a reason you don't want to use `MyTemplate` instead of `MyTemplate, std::pair, std::pair>`? You'll be able to easily generate the list of `pair` types in the template, AND you wouldn't need to extract the first type. – HolyBlackCat Jan 26 '19 at 00:00

1 Answers1

3

For now we can assume that MyTemplate will take only list of pair types. Moreover, all pair types should have the same first type and second type have to vary.

I want to "catch" the pairs' first_type in MyTemplate.

Not sure but it seems to me that your looking something as follows

template <typename...>
struct MyTemplate;

template <typename FT, typename ... STs>
struct MyTemplate<std::pair<FT, STs>...>
 {
   using first_type = FT;
 };

You can verify

using Alias = MyTemplate<std::pair<int, char>,
                         std::pair<int, double>,
                         std::pair<int, unsigned int>>;

static_assert( std::is_same<int, typename Alias::first_type>::value, "!" );

This way you also impose that the template parameters of MyTemplate are all std::pairss with a common first_type.

Otherwise, without template specialization and maintaining you way, you can use std::tuple/std::tuple_element_t

template <typename ... Ts>
struct MyTemplate
 {
   using first_type = std::tuple_element_t<0, std::tuple<typename Ts::first_type...>>;
 };
Community
  • 1
  • 1
max66
  • 65,235
  • 10
  • 71
  • 111