【发布时间】:2021-05-23 04:58:12
【问题描述】:
这是一个关于模板参数用作模板参数与用作默认模板参数与返回类型时模板推导如何工作的问题。
1:普通模板参数
经测试,使用 GCC 和 VS 编译以下 sn-p 无法推断出 std::enable_if_t 定义的模板参数
#include <iostream>
#include <type_traits>
template< class T, std::enable_if_t< std::is_integral_v< T > > >
void SwapInPlace( T& left, T& right )
{
left = left ^ right;
right = left ^ right;
left = left ^ right;
}
template< class T, std::enable_if_t< std::is_floating_point_v< T > > >
void SwapInPlace( T& left, T& right )
{
left = left - right;
right = left + right;
left = right - left;
}
int main()
{
int i1 = 10;
int i2 = -120;
std::cout << i1 << " " << i2 << std::endl;
SwapInPlace( i1, i2 );
std::cout << i1 << " " << i2 << std::endl;
double d1 = 1.1234;
double d2 = 2.5678;
std::cout << d1 << " " << d2 << std::endl;
SwapInPlace( d1 , d2 );
std::cout << d1 << " " << d2 << std::endl;
return 0;
}
VS: 错误 C2783: 'void SwapInPlace(T &,T &)': 无法推断 '__formal' 的模板参数
GCC:无法推断模板参数-anonymous-
2:默认模板参数
将第二个模板参数声明为默认模板参数使得推导工作正常:
template< class T, class = std::enable_if_t< std::is_integral_v< T > > >
void SwapInPlace( T& left, T& right )
{...}
template< class T, class = std::enable_if_t< std::is_floating_point_v< T > >, bool = true >
void SwapInPlace( T& left, T& right )
{...}
将bool = true 添加到第二次重载只是为了避免编译错误,因为无法根据默认模板参数重载函数模板。只想专注于扣除在这里可以正常工作的事实。如果只有一个模板使用默认参数,例如对于std::is_integral,只要我们将正确的参数传递给它,它就会编译并正常工作。
3:返回类型
在返回类型的情况下,一切都可以编译并且运行良好:
template< class T >
std::enable_if_t < std::is_integral_v< T > >
SwapInPlace( T& left, T& right )
{...}
template< class T >
std::enable_if_t < std::is_floating_point_v< T > >
SwapInPlace( T& left, T& right )
{...}
4:带默认值的模板参数
另一种编译此代码的方法是为std::enable_if 定义的模板参数添加默认值。在最后一个右尖括号之前添加了* = nullptr,因此如果std::enable_if 条件评估为true,那么我们的第二个参数变为void*,默认值为nullptr:
template< class T, std::enable_if_t< std::is_integral_v< T > >* = nullptr >
void SwapInPlace( T& left, T& right )
{...}
template< class T, std::enable_if_t< std::is_floating_point_v< T > >* = nullptr >
void SwapInPlace( T& left, T& right )
{...}
所以问题是:在这 4 种情况下如何演绎:为什么它在第一种情况下失败而在其他三种情况下成功?
【问题讨论】:
-
它与
enable_if没有任何关系,因此您可以大大简化问题。你想知道为什么template<class T, void>不起作用,但为什么template<class T, void* = nullptr>起作用,对吧? -
@TedLyngmo 不完全是,我想知道为什么它有效,为什么它不适用于我列出的案例。我最好奇为什么这适用于使用默认模板参数的情况。但我仍然想了解所有其他情况。
-
是的,我说你得到完全相同的没有混入
enable_if。 example -
@TedLyngmo 当然。那我需要重写问题。
标签: c++ sfinae template-argument-deduction enable-if function-templates