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 类型中替换失败是可能的,所以它是签名比较的一部分。您仍然可以潜在地生成两个冲突的特化来重载(在一般情况下,不是在示例中),但模板会有所不同。