16

众所周知,仅返回类型不同的普通函数不能在 C++ 中重载。

但是这个限制不适用于重载的函数模板,例如:

int f(auto) { return 1; }
auto f(auto) { return 2; }

所有编译器都接受它,演示:https ://gcc.godbolt.org/z/qj73Mzehd

为什么语言对模板做出这样的例外?

如果重载函数的返回类型不同,则可以使用强制转换为预期函数类型来选择其中一个函数。令人惊讶的是,即使返回类型实际上相同,Clang 也允许人们解决歧义,例如:

((int(*)(int))f)(3);

选择

int f(auto) { return 1; }

演示:https ://gcc.godbolt.org/z/snfvbq1ME

Clang在这里错了吗?

4

1 回答 1

12

为什么语言对模板做出这样的例外?

你是这个意思?

签名 [defns.signature.templ]

⟨函数模板⟩名称、参数类型列表、封闭命名空间(如果有)、返回类型、模板头和尾随要求子句(如果有)

是的,返回类型在那里。这就是让事情成为可能的原因

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

于 2021-09-30T07:51:11.907 回答