user997112
user997112

Reputation: 30615

Choose member type based on template arguments?

If I have a template class:

template<int N>
class C{
    Something _x;
}

I would like to control the type of class member _x depending on the value of N. Say if N was 0 then _x should be type A, else _x should be type B.

Is this possible?

I don't want to just pass the type as a template parameter because it might be possible to violate the rule determining which type to use. For example I could do C<1, A> which is incorrect.

Upvotes: 3

Views: 2592

Answers (3)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

There are many ways to do this. I like doing overloading, as it permits easy extensibility.

template<int N>using int_t=std::integral_constant<int,N>;
template<class T>struct tag_t{
  using type=T;
  constexpr tag_t()=default;
};
template<class Tag>
using type_t=typename Tag::type;

struct A{};
struct B{};

inline tag_t<A> something(int_t<0>){return {};}
template<int x>
inline tag_t<B> something(int_t<x>){return {};}

now we just:

template<int N>
class M {
public:
  type_t<decltype(something(int_t<N>{}))> _x;
};

the only advantage is you get the full power of overload resolution to pick the type, and you don't have to mess with template specialization, and you don't have to make one complex conditional to cover many cases.

If you are picking between two types with simple logic this is overkill.

Upvotes: 2

R Sahu
R Sahu

Reputation: 206577

Is this possible?

Yes. It's not too difficult either.

template<int N>
class C{
    typename c_member<N>::type _x;
}

where

struct A {};
struct B {};

template <int N> struct c_member
{
   using type = B;
};

template <> struct c_member<0>
{
   using type = A;
};

You can add more specializations of c_member if you want to.

Upvotes: 5

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29022

For a scenario where there are only a few possible types, you can use std::conditional.

#include <type_traits>

struct A {};
struct B {};

template<int N>
class M {
public:
    std::conditional_t<N == 0, A, B> _x;
};

Upvotes: 8

Related Questions