Why this does not compile with gcc48 and clang32?
#include
template
struct S {
template
typename
Well, I am not sure what you wanted to do, but maybe this code will help:
#include <iostream>
template <int N>
struct S {
template<class T=int>
typename std::enable_if<N==1, T>::type
f(T t) {return 1;}
template<class T=int>
typename std::enable_if<N!=1, T>::type
f(T t) {return 2;}
};
int main()
{
S<1> s1;
S<2> s2;
std::cout << s1.f(99) << " " << std::endl << s2.f(5);
}
This prints 1 and 2.
To get std::enable_if
to work like this, you are relying on SFINAE. Unfortunately, at the point where you declare
S<1> s1;
it will instantiate all of S<1>
's member declarations. SFINAE will only come into play at this point if S<1>
were an ill-formed construct. It is not. Unfortunately, it contains a function which is invalid, thus the instantiation of S<>
is invalid.
For things like this, I might defer to a seperate template struct:
template <bool B>
struct f_functor {
template <typename T>
static int f(T t) { return 1; }
};
template <>
struct f_functor<false> {
template <typename T>
static int f(T t) { return 2; }
};
template <int N>
struct S {
template<class T>
typename int f(T t) { return f_functor<N==1>::f(t); }
};
For this case you could think about not using enable_if at all. It is posible to simply specialise f:
template <int N>
struct S {
template<class T> int f(T t);
};
template<int N>
template<class T>
int S<N>::f(T t) { return 2; }
template<>
template<class T>
int S<1>::f(T t) { return 1; }
int main() {
S<1> s1;
return s1.f(99);
}
Use a default boolean template parameter, like this:
template <int N>
struct S {
template<class T, bool EnableBool=true>
typename std::enable_if<N==1 && EnableBool, int>::type
f(T t) {return 1;};
template<class T, bool EnableBool=true>
typename std::enable_if<N!=1 && EnableBool, int>::type
f(T t) {return 2;};
};
Because you use enable_if
without using the template parameter T
in your function templates. If you want to specialize for when the struct S
has a certain template parameter value N
, you'll need to use class template specialization.
template <int N, class Enable = void>
struct S { };
template <int N>
struct S<N, typename std::enable_if<N == 1>::type>
{
....
};