19
struct Bar {
  enum { Special = 4 };
};

template<class T, int K> struct Foo {};
template<class T> struct Foo<T,T::Special> {};

Usage:

Foo<Bar> aa;

fails to compile using gcc 4.1.2 It complains about the usage of T::Special for partial specilization of Foo. If Special was a class the solution would be to a typename in front of it. Is there something equivalent to it for enums (or integers)?

svick
  • 236,525
  • 50
  • 385
  • 514
Altan
  • 221
  • 3
  • 5
  • If you replace T::Special with a concrete integer (99, say), it still doesn't compile under g++ 4.4.0: 'wrong number of template arguments (1, should be 2)'.I realise this is a separate issue, but shouldn't the compiler accept this? – TonyK Dec 28 '10 at 08:35

2 Answers2

16

Since that is not allowed by C++ as explained by Prasoon, so an alternative solution would be to use EnumToType class template,

struct Bar {
  enum { Special = 4 };
};

template<int e>
struct EnumToType
{
  static const int value = e;
};

template<class T, class K> //note I changed from "int K" to "class K"
struct Foo
{};

template<class T> 
struct Foo<T, EnumToType<(int)T::Special> > 
{
   static const int enumValue = T::Special;
};

Sample code at ideone : http://www.ideone.com/JPvZy


Or, you can simply specialize like this (if it solves your problem),

template<class T> struct Foo<T,Bar::Special> {};

//usage
Foo<Bar, Bar::Special> f;
Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Note that you can use `enum` inside `EnumToType` instead of `static const int`. Also, the standard (C++0x, Boost) name for `EnumToType` is `integral_constant`. – Potatoswatter Dec 28 '10 at 08:19
8

The type of a non-type template argument cannot depend on a template parameter of a partial specialization.

ISO C++03 14.5.4/9 says

A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier.

template <int I, int J> struct A {};
template <int I> struct A<I+5, I*2> {}; //error
template <int I, int J> struct B {};
template <int I> struct B<I, I> {};     //OK

So something like this is illegal template<class T> struct Foo<T,T::Special> {}; because T::Special depends on T

The usage is also illegal. You have provided one template argument but you need to provide two.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345