2

One often sees SFINAE used for functions. For example:

#include <type_traits>
#include <iostream>

template<int N>//version for N!=4
typename std::enable_if<N==4, int>::type val(){
    return N;
}

template<int N>//version for N==4
typename std::enable_if<N!=4, int>::type val(){
    return 2*N;
}

int main(){
  std::cout<<val<4>()<<std::endl;//prints: 4, version N==4
  std::cout<<val<5>()<<std::endl;//prints: 10, version N==10
}

Can I use SNIFAE not only for functions but also for structs? Something like:

...
template<int N, typename std::enable_if<N==4>::type>
struct S{
    int v;//for N==4 v  should be int
    ...
};

template<int N, typename std::enable_if<N!=4>::type>
struct S{
    long v;//for N!=4 v  should be long
    ...
};

The compiler does not accept it, even if I don't try to instantiate.

What is the right way to use SFINAE with structs?

Or should one use a different technique in order to achieve the goal of having different struct-members for different N values?

PS: Using SFINAE for N==4 does not make much sense, please consider it to be a place holder for more complicated constrains.

Edit: I was not aware, that SFINAE is only for functions and not for classes. std::conditinal is a way out if there are only two possibilities. If there are more than two different behaviours one would like to pick from, than the answer to the question shown by the community is a possible solution.

Community
  • 1
  • 1
ead
  • 32,758
  • 6
  • 90
  • 153
  • 2
    SFINAE is about function overload resolution, so it's not clear what your question means. It looks like you just want class template specialization. – Kerrek SB Feb 07 '16 at 14:30

1 Answers1

3

It looks like all you want is class template specialization:

template <int N> struct S
{
    long v;
    // ...
};

template <> struct S<4>
{
    int v;
    // ...
};

Complexity can be managed by factoring such choices into separate trait class templates and then using a dependent type such as typename type_picker<N>::type v;. Or you can use a ready-made picker: typename std::conditional<N == 4, int, long>::type v;.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Thanks for the suggestion! But what if I need different implementations for "N is even" and "N is odd" or even more complicated. Can it be also done by means of template specialization? – ead Feb 07 '16 at 14:35
  • 1
    @ead: Yes, it can. You can specialize on some intermediate selector parameter, e.g. a boolean, like `std::conditional` does it. – Kerrek SB Feb 07 '16 at 14:35