问题描述
这是一个关于当模板参数用作模板参数 vs 作为默认模板参数 vs 作为返回类型时模板推导如何工作的问题。
1:普通模板参数
如使用 GCC 和 VS 编译测试,以下代码片段未能推导出由 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,std::enable_if_t< std::is_floating_point_v< T > >* = nullptr >
void SwapInPlace( T& left,T& right )
{...}
所以问题是:在这 4 种情况下如何演绎:为什么它在第一种情况下失败而在其他三种情况下成功?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)