sd_
sd_

Reputation: 105

Traits class implementation for generic types with different type params

I have the following traits class

template<typename T> struct FeatureType;

and I'm using it like so, which works fine:

class Foo { };
template<> struct FeatureType<Foo> {
  typedef int value;
};

template<typename T> class Bar { };
template<typename T> struct FeatureType<Bar<T>> {
  typedef T value;
};

Is there a way to extent this implementation for generic types to those that have more than one type parameter (unlike Bar above)? The following does not work

template<typename A, typename B> class Huh { };
template<typename A, typename B> struct FeatureType<Huh<A,B>> {
  typedef A value;
};

Thanks!

Upvotes: 1

Views: 224

Answers (2)

TemplateRex
TemplateRex

Reputation: 70526

Regular templates

Regular templates do not overload on their template parameters, but you can partially specialize them on arbitrary many template parameters. Your code should work as long as you put ; behind every struct declaration/definition. (note it is a custom to denote nested types inside templates as type, and values as value):

#include <iostream>

template<typename T>
struct FeatureType;

class Foo { };
template<> struct FeatureType<Foo> 
{
  typedef int type;
  type value;
};

template<typename T> class Bar { };
template<typename T> struct FeatureType<Bar<T>> 
{
  typedef T type;
  type value;
};

template<typename A, typename B> class Huh {};
template<typename A, typename B>
struct FeatureType< Huh<A,B> > 
{ 
   typedef A type; 
   type value;
};

int main()
{
  FeatureType<Foo> f0;
  f0.value = 0;

  FeatureType< Bar<int> > f1;
  f1.value = 1;

  FeatureType< Huh<int, int> > f2;
  f2.value = 2;

  std::cout << f0.value << f1.value << f2.value;   
}

Output on LiveWorkSpace (gcc 4.7.2)

Note: even if you have multiple formal template parameters (A, B, or as many as you like), the actual template is partially specialized for the single class Huh<A, B>

Variadic templates

If you actually want to have multiple versions of FeatureType taking a different number of template parameters, you need to use variadic templates (C++11)

#include <iostream>

template<typename... Args>
struct FeatureType;

template<> struct FeatureType<int> 
{
  typedef int type;
  type value;
};

template<typename T> struct FeatureType< T > 
{
  typedef T type;
  type value;
};

template<typename A, typename B>
struct FeatureType< A, B > 
{ 
   typedef A type; 
   type value;
};

int main()
{
  FeatureType< int > f0;
  f0.value = 0;

  FeatureType< int > f1;
  f1.value = 1;

  FeatureType< int, int > f2;
  f2.value = 2;

  std::cout << f0.value << f1.value << f2.value;   
}

Output on LiveWorkSpace

Upvotes: 1

Joseph Mansfield
Joseph Mansfield

Reputation: 110658

I'm not sure exactly what you tried, but you sure can specialize with as many template arguments as you like:

template <typename A, typename B>
class foo { };

template <typename T>
struct feature_type {};

template <typename A, typename B>
struct feature_type<foo<A,B>> {
  typedef A type1;
  typedef A type2;
};

int main(int argc, const char* argv[])
{
  typename feature_type<foo<int,char>>::type1 x;
  typename feature_type<foo<int,char>>::type2 y;
  return 0;
}

See it in action.

Upvotes: 0

Related Questions