为什么具有推导的返回类型的模板不能与其他版本的类重载? [英] Why is a template with deduced return type not overloadable with other versions of it?

查看:186
本文介绍了为什么具有推导的返回类型的模板不能与其他版本的类重载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么以下两个模板不兼容,无法重载?

Why are the following two templates incompatible and can't be overloaded?

#include <vector>

template<typename T>
auto f(T t) { return t.size(); }
template<typename T>
auto f(T t) { return t.foobar(); }

int main() {
   f(std::vector<int>());   
}



我认为它们(或多或少) (我们不能做 decltype auto(t.size())我不能给一个精确的等价没有一些噪音..)。

I would think they are (more or less) equivalent with the following which compiles fine (as we cannot do decltype auto(t.size()) I can't give an exact equivalent without some noise..).

template<typename T>
auto f(T t) -> decltype(t.size() /* plus some decay */) { return t.size(); }

template<typename T>
auto f(T t) -> decltype(t.foobar() /* plus some decay */) { return t.foobar(); }

Clang和GCC抱怨 main.cpp:6:16:重新定义'f'如果我离开结尾返回类型,但是。

Clang and GCC complain main.cpp:6:16: error: redefinition of 'f' if I leave off the trailing return type, however.

(请注意,这是一个理由问题。我不是在标准中寻找定义这种行为的地方你也可以在你的答案中包含,如果你愿意的话 - 但是为什么这种行为是可取的或现状的解释。)

(Note that this is a rationale question. I am not seeking for the place in the Standard which defines this behavior - which you may include in your answer too, if you wish - but for an explanation of why this behavior is desirable or status-quo).

推荐答案

返回类型可能显然不是签名的一部分。
然而,从 return 语句推断确定返回类型(并且参与SFINAE)的表达式有一些问题。让我们假设我们采用第一个 return 语句的表达式,并将其粘贴到一些调整的虚拟结尾返回类型中:

The deduced return type can clearly not be part of the signature. However, inferring an expression that determines the return type (and participates in SFINAE) from return statements has some issues. Let's say we were to take the first return statement's expression and paste it into some adjusted, virtual trailing-return-type:


  1. 如果返回的表达式取决于 local 声明,该怎么办?这不一定阻止我们,但它扼杀了规则。不要忘记,我们不能使用声明的实体的名称;

  1. What if the returned expression depends on local declarations? This isn't necessarily stopping us, but it snarls the rules tremendously. Don't forget that we can't use the names of the entities declared; This could potentially complex our trailing-return-type sky-high for potentially no benefit at all.

这个功能的一个受欢迎的用例是函数模板返回 lambdas 。然而,我们几乎不能将签名的lambda部分 - 将出现的复杂性已经详细阐述了之前。单独的Mangling需要英勇的努力。因此,我们必须使用lambdas排除函数模板。

A popular use case of this feature are function templates returning lambdas. However, we can hardly make a lambda part of the signature - the complications that would arise have been elaborated on in great detail before. Mangling alone would require heroic efforts. Hence we'd have to exclude function templates using lambdas.

无法确定声明的签名也是一个定义,引入了一整套其他问题。最简单的解决方案是完全禁止(非定义)这些函数模板的声明,这是非常可笑的。

The signature of a declaration couldn't be determined if it wasn't a definition also, introducing a whole set of other problems. The easiest solution would be to disallow (non-defining) declarations of such function templates entirely, which is almost ridiculous.

幸运的是,N3386的作者努力保持规则(和实现!)简单。我不能想象在某些情况下,如何自己写一个尾随返回类型是值得这样细致的规则。

Fortunately the author of N3386 strove to keep the rules (and implementation!) simple. I can't imagine how not having to write a trailing-return-type yourself in some corner cases warrants such meticulous rules.

这篇关于为什么具有推导的返回类型的模板不能与其他版本的类重载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆