使用 SFINAE 进行结构定义

Using SFINAE for structs definitions

人们经常看到 SFINAE 用于函数。例如:

#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
}

我可以将 SNIFAE 不仅用于函数而且用于结构吗?类似于:

...
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
    ...
};

即使我不尝试实例化,编译器也不接受。

将 SFINAE 与结构一起使用的正确方法是什么?

或者应该使用不同的技术来实现为不同的 N 值使用不同的结构成员的目标?

PS:将 SFINAE 用于 N==4 没有多大意义,请将其视为更复杂约束的占位符。

编辑: 我不知道 SFINAE 仅用于函数而不用于 类。如果只有两种可能,std::conditinal是一条出路。如果有两种以上的不同行为可供选择,那么 question shown by the community 的答案是一种可能的解决方案。

看起来你想要的只是class模板专业化:

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

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

可以通过将此类选择分解为单独的特征 class 模板,然后使用依赖类型(例如 typename type_picker<N>::type v;)来管理复杂性。或者您可以使用现成的选择器:typename std::conditional<N == 4, int, long>::type v;.