两种模板代码模式之间的差异,一种情况下分配了数字,而另一种情况下使用关键字 typename

joh*_*456 4 c++ templates sfinae c++14

在下面的代码中,下面两个模板行有什么区别。

>      1. template<class T, std::enable_if_t<std::is_integral<T>::value, int> = 0> 
>      2. template<class T, typename = std::enable_if_t<std::is_integral<T>::value>>
Run Code Online (Sandbox Code Playgroud)

以上两条线都工作正常,我只是想知道使用其中一条线的优势/劣势。

#include <type_traits>
#include <iostream>
template<class T, std::enable_if_t<std::is_integral<T>::value, int> = 0>

//template<class T, typename = std::enable_if_t<std::is_integral<T>::value>>


int onlyOnInt(T a, T b)
{
    return a+b;
}
int main()
{
    onlyOnInt(1, 2);
}
Run Code Online (Sandbox Code Playgroud)

max*_*x66 6

如果您编写单个函数,它们都可以正常工作。

但是当你想要两个替代功能时,这样

template <typename T, typename = std::enable_if_t<true == std::is_integral_v<T>>>
void foo (T const &)
 { std::cout << "is integral" << std::endl; }

template <typename T, typename = std::enable_if_t<false == std::is_integral_v<T>>>
void foo (T const &)
 { std::cout << "isn\'t integral" << std::endl; }
Run Code Online (Sandbox Code Playgroud)

以这种方式出现编译错误

template <typename T, std::enable_if_t<true == std::is_integral_v<T>, int> = 0>
void foo (T const &)
 { std::cout << "is integral" << std::endl; }

template <typename T, std::enable_if_t<false == std::is_integral_v<T>, int> = 0>
void foo (T const &)
 { std::cout << "isn\'t integral" << std::endl; }
Run Code Online (Sandbox Code Playgroud)

作品。

原因?

考虑您正在玩 SFINAE,即替换失败不是错误。

重点是换人。

第一种方式,当你打电话

foo(0)
Run Code Online (Sandbox Code Playgroud)

替代带来

template <typename T, typename = void>
void foo (T const &)
 { std::cout << "is integral" << std::endl; }

template <typename T, typename>
void foo (T const &)
 { std::cout << "isn\'t integral" << std::endl; }
Run Code Online (Sandbox Code Playgroud)

也就是说......你有两个具有相同签名的函数(默认模板参数不会改变函数的签名)和调用它的冲突。

在第二种方式中,你只有

template <typename T, int = 0>
void foo (T const &)
 { std::cout << "is integral" << std::endl; }
Run Code Online (Sandbox Code Playgroud)

因为第二个函数中的替换失败使该函数无法使用并被丢弃。所以你只有一个可用的功能并且没有碰撞。