std::enable_if使用它的内部类型,而不使用它

std::enable_if using its internal type and without using it

本文关键字:类型 内部 if enable std      更新时间:2023-10-16

为什么要打印"B"

#include <iostream>
template<typename T, typename U = void>
struct Test
{ static void apply() { std::cout << "A" << std::endl; } };
template<typename T>
struct Test<T, typename std::enable_if<true>::type>
{ static void apply() { std::cout << "B" << std::endl; } };
int main()
{
    Test<int>::apply();
}

但是这个"A"?:

#include <iostream>
template<typename T, typename U = void>
struct Test
{ static void apply() { std::cout << "A" << std::endl; } };
template<typename T>
struct Test<T, std::enable_if<true>>
{ static void apply() { std::cout << "B" << std::endl; } };
int main()
{
    Test<int>::apply();
}

它们之间唯一的区别是,在第一个例子中,我使用typename std::enable_it<true>::type作为U(例如void),但在第二个例子中我直接使用std::enable_if<true>作为U,这也是一个定义良好的类型,与void没有更多意义。

因为当您编写Test<int>时,实际上是在编写Test<int, void>,它永远不会与Test<int, std::enable_if<true>>相同(尽管它与Test<int, typename std::enable_if<true>::type>相同)

由于typename std::enable_if<true>::typevoid的类型相同,因此第一个代码段等效于

template<typename T, typename U = void>
struct Test
{ static void apply() { std::cout << "A" << std::endl; } };
template<typename T>
struct Test<T, void> // since typename std::enable_if<true>::type == void
{ static void apply() { std::cout << "B" << std::endl; } };

因此,第二个定义是更专业的,因此,如果不提供两个模板参数,后者将在过载解决中获胜。

然而,在第二个示例中,它只是对类型Tstd::enable_if<true>的专门化,而不是对Tvoid的专门化。这可以用std::is_same<std::enable_if<true>, void>进行检查,它的计算结果为false(很明显,void没有类型成员type,所以它不可能相同)。

因此,对于第二个片段,请求T<int>将与只有一个定义相关的T<int, void>匹配,即第一个定义。