为什么这个函数不能用明显不同的签名之一重载?
Why can't this function be overloaded with one of clearly different signature?
由于error: redefinition of ‘template<class Integer, class> void func(Integer)’
,以下代码编译失败
#include <iostream>
#include <type_traits>
template<typename Float, typename = typename
std::enable_if<std::is_floating_point<Float>::value>::type>
void func(Float floatVal)
{
std::cerr << "float: " << floatVal << "\n";
}
template<typename Integer, typename = typename
std::enable_if<std::is_integral<Integer>::value>::type>
void func(Integer integer)
{
std::cerr << "integral: " << integer << "\n";
}
int main()
{
func(32.4246);
func(144532);
}
但这两个函数显然在模板实例化上具有不同的签名。那为什么不能编译呢?
请注意:我确实知道如何解决这个问题:只需向其中一个函数添加另一个虚拟模板参数,例如typename=void
,会像这里一样工作
template<typename Integer, typename dummy=void, typename = typename
std::enable_if<std::is_integral<Integer>::value>::type>
void func(Integer integer){}
但问题是为什么我必须这样做?
您可以将 std::enable_if<...>::type
更改为函数的 return 类型。据我所知,您不能将它传递给另一个模板参数的类型。
#include <iostream>
#include <type_traits>
template<typename Float>
typename std::enable_if<std::is_floating_point<Float>::value>::type
func(Float floatVal)
{
std::cerr << "float: " << floatVal << "\n";
}
template<typename Integer>
typename std::enable_if<std::is_integral<Integer>::value>::type
func(Integer integer)
{
std::cerr << "integral: " << integer << "\n";
}
int main()
{
func(32.4246);
func(144532);
}
或者像 那样重载 return 类型,你可以在模板类型中稍微复杂一点:
template<typename Float, typename std::enable_if<std::is_floating_point<Float>::value>::type* = nullptr>
void func(Float floatVal)
{
std::cerr << "float: " << floatVal << "\n";
}
template<typename Integer, typename std::enable_if<!std::is_floating_point<Integer>::value && std::is_integral<Integer>::value>::type* = nullptr>
void func(Integer integer)
{
std::cerr << "integral: " << integer << "\n";
}
Live Demo
请注意,Integer
的第二个 enable_if
明确否定了 Float
的 enable_if
条件
这种方法的好处是您的函数仍然 return void
并测试它:
int main()
{
func(32.4246);
func(144532);
}
输出:
float: 32.4246
integral: 144532
N4527 §1.3.19 [defns.signature.templ]
signature
<function template> name, parameter type list (8.3.5), enclosing namespace (if any), return type, and
template parameter list
默认模板参数不是函数模板签名的一部分。
由于error: redefinition of ‘template<class Integer, class> void func(Integer)’
#include <iostream>
#include <type_traits>
template<typename Float, typename = typename
std::enable_if<std::is_floating_point<Float>::value>::type>
void func(Float floatVal)
{
std::cerr << "float: " << floatVal << "\n";
}
template<typename Integer, typename = typename
std::enable_if<std::is_integral<Integer>::value>::type>
void func(Integer integer)
{
std::cerr << "integral: " << integer << "\n";
}
int main()
{
func(32.4246);
func(144532);
}
但这两个函数显然在模板实例化上具有不同的签名。那为什么不能编译呢?
请注意:我确实知道如何解决这个问题:只需向其中一个函数添加另一个虚拟模板参数,例如typename=void
,会像这里一样工作
template<typename Integer, typename dummy=void, typename = typename
std::enable_if<std::is_integral<Integer>::value>::type>
void func(Integer integer){}
但问题是为什么我必须这样做?
您可以将 std::enable_if<...>::type
更改为函数的 return 类型。据我所知,您不能将它传递给另一个模板参数的类型。
#include <iostream>
#include <type_traits>
template<typename Float>
typename std::enable_if<std::is_floating_point<Float>::value>::type
func(Float floatVal)
{
std::cerr << "float: " << floatVal << "\n";
}
template<typename Integer>
typename std::enable_if<std::is_integral<Integer>::value>::type
func(Integer integer)
{
std::cerr << "integral: " << integer << "\n";
}
int main()
{
func(32.4246);
func(144532);
}
或者像
template<typename Float, typename std::enable_if<std::is_floating_point<Float>::value>::type* = nullptr>
void func(Float floatVal)
{
std::cerr << "float: " << floatVal << "\n";
}
template<typename Integer, typename std::enable_if<!std::is_floating_point<Integer>::value && std::is_integral<Integer>::value>::type* = nullptr>
void func(Integer integer)
{
std::cerr << "integral: " << integer << "\n";
}
Live Demo
请注意,Integer
的第二个 enable_if
明确否定了 Float
enable_if
条件
这种方法的好处是您的函数仍然 return void
并测试它:
int main()
{
func(32.4246);
func(144532);
}
输出:
float: 32.4246
integral: 144532
N4527 §1.3.19 [defns.signature.templ]
signature
<function template> name, parameter type list (8.3.5), enclosing namespace (if any), return type, and template parameter list
默认模板参数不是函数模板签名的一部分。