没有名称的C++模板参数

C++ template argument without a name

本文关键字:参数 C++ 有名称      更新时间:2023-10-16

我遇到了以下代码片段:

template <typename T, typename = void>
struct test {
int t = sizeof(T);
};

我知道在typename = void中,void是默认参数,但它没有名称!它对什么有用?它到底意味着什么?

这与SFINAE一起用于专业化。这样做可以让你拥有类似的代码

template <typename T, typename = void>
struct test {
int t = sizeof(T);
};
template <typename T>
struct test<T, std::enable_if_t<std::is_integral_v<T>>> {
//             ^^  this part "fills in" the void    ^^
int t = 42;
};
template <typename T>
struct test<T, std::enable_if_t<std::is_floating_point_v<T>>> {
//             ^^     this part "fills in" the void       ^^
int t = 21;
};
int main()
{
test<int> i;
std::cout << i.t << "n";
test<double> d;
std::cout << d.t;
}

输出

42
21

如果没有typename = void,我们将无法添加这些专业化,因为enable_if_t部分将无法"填充"第二个参数。

我个人喜欢将其视为默认模板(类型(参数的情况,以排除不符合某些标准的重载。首先,为默认模板参数命名是很好的,所以以下内容是正确的:

template <typename T, typename sometype= void>
struct test {
int t = sizeof(T);
};

在上面的例子中,类型参数sometype显然没有在结构测试中的任何地方使用。但是,如果我们不将默认值设置为void,而是使用一些编译时条件将其设置为模板函数仅对这样的积分类型有效,该怎么办?

(借用nathan答案中的代码(

template <typename T>
struct test<T, typename sometype = std::enable_if_t<std::is_integral_v<T>>> {          
int t = 42;
};

如果T的类型为integral,则定义sometype,否则使用sfinae忽略给定的模板。

此外,您可以将";CCD_ 6";写入:

template <typename T>
struct test<T, typename = std::enable_if_t<std::is_integral_v<T>>> {          
int t = 42;
};

最后将其与函数声明中使用的默认值进行比较:

void foo(int = 9);  //Function declaration can have default values without names too.
void foo (int a ) 
{
//some code
}

除了其他人的聪明答案来描述初始问题使用传统的模板元编程的SFINAE规则,

我可以补充一点,我们现在可以通过名为<概念>头,它支持约束——给定模板类型和模板值的条件或子情况。

更多信息,请访问https://en.cppreference.com/w/cpp/language/constraints