我遇到了函数重载的顺序很重要的情况。
我以为原因一定是带有val1 value1
val2 value2
val3 value3
的SFINAE部分((我另外测试了没有std::enable_if
的代码,仅使用模板,然后代码运行,而不管函数重载的顺序。))< / p>
我从中做了一个最小的工作例子。
此代码块有效
std::enable_if
以下内容无法编译(交换了#include <type_traits>
template <bool C, typename R = void>
using EnableIf = typename std::enable_if<C, R>::type;
template <typename T, typename R = void>
using IfIsArithmetic = EnableIf<std::is_arithmetic<T>::value, R>;
template <typename S>
IfIsArithmetic<S, void> Add(S const &scalar1, S const &scalar2, S &ret)
{
ret = scalar1 + scalar2;
}
template <typename S>
IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
{
S ret;
Add(scalar1, scalar2, ret);
return ret;
}
using T = float;
int main(){
T a = 3.1;
T b = 3.5;
T c{Add(a, b)};
}
函数的实现)
Add()
编译器出现以下错误
#include <type_traits>
template <bool C, typename R = void>
using EnableIf = typename std::enable_if<C, R>::type;
template <typename T, typename R = void>
using IfIsArithmetic = EnableIf<std::is_arithmetic<T>::value, R>;
template <typename S>
IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
{
S ret;
Add(scalar1, scalar2, ret);
return ret;
}
template <typename S>
IfIsArithmetic<S, void> Add(S const &scalar1, S const &scalar2, S &ret)
{
ret = scalar1 + scalar2;
}
using T = float;
int main(){
T a = 3.1;
T b = 3.5;
T c{Add(a, b)};
}
似乎,即使签名未对齐,编译器也会尝试使用第一个函数重载。
也许有些人可以给我提示,此问题与C ++函数查找规则有关!
答案 0 :(得分:3)
似乎,即使签名未对齐,编译器也会尝试使用第一个函数重载。
完全正确。
顺序很重要。
编译Add(S const &scalar1, S const &scalar2)
的主体时,编译器不知道在其后将定义带有三个参数的Add()
。因此,请尝试(目前)唯一已知的Add()
,但参数数量不匹配。
SFINAE,模板和using
都不是问题:同样,您也会遇到相同的错误
float Add (float const &scalar1, float const &scalar2)
{
float ret;
Add(scalar1, scalar2, ret);
return ret;
}
void Add(float const &scalar1, float const &scalar2, float &ret)
{
ret = scalar1 + scalar2;
}
int main(){
float a = 3.1;
float b = 3.5;
float c{Add(a, b)};
}
如果您确实要在树形参数第一个之前定义两个参数Add()
,则必须说在Add()
的两个参数版本的定义之前,编译器应指定三个参数的版本跟随;您可以这样声明(未定义)三个参数的版本
void Add (float const &, float const &, float &);
float Add (float const &scalar1, float const &scalar2)
{
float ret;
Add(scalar1, scalar2, ret);
return ret;
}
void Add(float const &scalar1, float const &scalar2, float &ret)
{
ret = scalar1 + scalar2;
}
这在两个函数相互调用的情况下很有用。
在第二个示例中,您可以添加三个参数Add()
template <typename S>
IfIsArithmetic<S, void> Add(S const &, S const &, S &);
在定义两个参数版本之前。
关闭主题
从C ++ 14开始,您可以使用std::enable_if_t
,该定义(据我所知)与您的EnableIf
完全一样。
从C ++ 17开始,您还可以使用std::is_arithmetic_v<T>
代替std::is_arithmetic<T>::value
。