为什么不能用明显不同的签名之一重载此函数?

Why can't this function be overloaded with one of clearly different signature?

本文关键字:重载 函数 不能 为什么      更新时间:2023-10-16

由于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){}
但问题是为什么我必须这样做?

N4527 §1.3.19 [define .signature.templ]

可以将std::enable_if<...>::type更改为函数的返回类型。据我所知,你不能把它传递给另一个模板参数的类型。

#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);
}
<<p> 生活例子/kbd>

或者像NathanOliver那样重载返回类型,你可以在模板类型中更复杂一点:

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";
}

现场演示注意,Integer的第二个enable_if显式地否定了Floatenable_if条件

这种方法的好处是函数仍然返回void

并测试它:

int main()
{
    func(32.4246);
    func(144532);
}
输出:

float: 32.4246
integral: 144532