C++ 中仅 return 类型不同的重载函数模板
Overloaded function templates that differ only in their return types in C++
众所周知,仅 return 类型不同的普通函数不能在 C++ 中重载。
但此限制不适用于重载函数模板,例如:
int f(auto) { return 1; }
auto f(auto) { return 2; }
所有编译器都接受它,演示:https://gcc.godbolt.org/z/qj73Mzehd
为什么语言对模板有这样的例外?
如果重载函数的 return 类型不同,则可以 select 使用转换为预期函数类型的函数之一。令人惊讶的是,即使 return 类型实际上相同,Clang 也允许人们解决歧义,例如:
((int(*)(int))f)(3);
selects
int f(auto) { return 1; }
演示:https://gcc.godbolt.org/z/snfvbq1ME
Clang这里是不是错了?
Why does the language make such exception for the templates?
你是这个意思?
signature [defns.signature.templ]
⟨function template⟩ name, parameter-type-list, enclosing namespace (if any), return type, template-head, and trailing requires-clause (if any)
是的,有 return 类型。它总是让
这样的事情成为可能
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type foo(T&);
template<typename T>
typename std::enable_if<!std::is_integral<T>::value>::type foo(T&);
SFINAE 是签名中包含 return 类型的原因。在 return 类型中替换失败是可能的,所以它是签名比较的一部分。您仍然可以潜在地生成两个冲突的特化来重载(在一般情况下,不是在示例中),但模板会有所不同。
众所周知,仅 return 类型不同的普通函数不能在 C++ 中重载。
但此限制不适用于重载函数模板,例如:
int f(auto) { return 1; }
auto f(auto) { return 2; }
所有编译器都接受它,演示:https://gcc.godbolt.org/z/qj73Mzehd
为什么语言对模板有这样的例外?
如果重载函数的 return 类型不同,则可以 select 使用转换为预期函数类型的函数之一。令人惊讶的是,即使 return 类型实际上相同,Clang 也允许人们解决歧义,例如:
((int(*)(int))f)(3);
selects
int f(auto) { return 1; }
演示:https://gcc.godbolt.org/z/snfvbq1ME
Clang这里是不是错了?
Why does the language make such exception for the templates?
你是这个意思?
signature [defns.signature.templ]
⟨function template⟩ name, parameter-type-list, enclosing namespace (if any), return type, template-head, and trailing requires-clause (if any)
是的,有 return 类型。它总是让
这样的事情成为可能template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type foo(T&);
template<typename T>
typename std::enable_if<!std::is_integral<T>::value>::type foo(T&);
SFINAE 是签名中包含 return 类型的原因。在 return 类型中替换失败是可能的,所以它是签名比较的一部分。您仍然可以潜在地生成两个冲突的特化来重载(在一般情况下,不是在示例中),但模板会有所不同。