使用 SFINAE 进行结构定义

Using SFINAE for structs definitions

本文关键字:结构 定义 SFINAE 使用      更新时间:2023-10-16

人们经常看到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就是一条出路。如果有两种以上的不同行为可供选择,那么社区显示的问题的答案是一个可能的解决方案。

看起来你想要的只是类模板专用化:

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

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