8

我一直在使用 -std=c++1y 玩 g++ 支持的返回类型推导。
如果您对具有显式返回类型的函数进行原型设计,然后尝试使用返回类型推导来定义该函数,编译器会抱怨一个模棱两可的旧声明:

std::string some_function();
...  
auto some_function(){ return std::string{"FOO"}; } //fails to compile

有充分的理由为什么这不起作用?
我在定义中使用返回类型推导的理由是保持代码干净,但出于自我记录的原因,希望在原型中使用显式类型。关于何时以及何时不使用返回类型扣除的最佳实践建议将不胜感激:)

为了更清楚,我想回答:
1.这是编译器中的实现错误吗?(我很确定不是)
2. 这种扣除方式可以做,但标准提案不允许吗?如果是这样,为什么不呢?
3. 如果这真的是模棱两可的,有哪些例子可以推断出类型并尝试将其与显式前向声明相匹配会给您带来麻烦?
4. 这背后是否存在更深层次的具体实施问题?
5. 仅仅是疏忽吗?

4

2 回答 2

6

这是因为函数表和重载函数在 C++ 中的工作方式。

当编译器读取你的std::string some_function();文件时,它会创建一个点供它在二进制文件中引用,并说是否“这个函数被调用过跳转到这个点”。

所以我们有一个看起来像这样的vtable......

(Address offset)  (Symbol)
0x????????       std::string somefunction();

现在它到达你的auto some_function() {...}. 通常它会首先在函数表中查看是否auto somefunction();存在于表中或表中是否存在一些变体,但编译器注意到这是一个实现并且它具有 auto 关键字以便减少它写入*blank* some_function();函数表的熵和关系解决返回类型。

现在函数表看起来像这样......

(Address offset)  (Symbol)
0x????????       std::string somefunction();
0x????????       ????? somefunction();

因此,当它发现返回类型(在本例中为std::string. 编译器现在知道返回类型是什么,因此它会转到函数表并进行auto somefunction();更改std::string somefunction();

现在函数表看起来像这样......

(Address offset)  (Symbol)
0x????????       std::string somefunction();
0x????????       std::string somefunction();

现在编译器返回并继续编译函数。完成后,它会返回并完成 vtable 只是发现相同的符号在那里两次。现在我们所指的符号也很模糊。

那么这是什么原因呢?

不是 100% 确定,但 vtables 是在您的代码被处理到足以允许进行扣除类型之前很久就制作的。因此,编译器在那个阶段必须使用的唯一选择就是假设它是一个新符号。这只是我注意到整天查看符号表并编写我自己的 C++11 编译器的东西。

但是,我不能代表其他引入了许多优化和其他步骤的编译器,我只是简单地工作,但这是我对标准的理解。

最后一件事,类型是完全任意的。即使他们在扣除时不匹配也没关系。它永远不会那么远。问题出现在表中有两个相同的符号,并且您不能重载返回类型。

于 2013-09-03T16:38:18.723 回答
-2

你需要这样做:

auto some_function() -> decltype(std::string) { return std::string{"FOO"}; } 

有关更多信息,请查看http://en.wikipedia.org/wiki/C%2B%2B11 -> 替代函数语法

于 2013-08-29T19:43:12.620 回答