使用C++中的显式原型返回类型推导

mio*_*ura 8 c++ return-type forward-declaration c++14

我一直在玩g ++支持的返回类型演绎与-std = c ++ 1y.
如果您使用显式返回类型对函数进行原型化,然后尝试使用返回类型推导来定义函数,则编译器会抱怨一个模糊的旧声明:

std::string some_function();
...  
auto some_function(){ return std::string{"FOO"}; } //fails to compile
Run Code Online (Sandbox Code Playgroud)

有什么理由不适用吗?
我在定义中使用返回类型推导的基本原理是保持代码干净,但是为了自我记录的原因需要原型中的显式类型.关于何时何时不使用退货类型扣除的最佳做法的建议将不胜感激:)

为了更清楚,我想回答:
1.这是编译器中的实现错误吗?(我很确定不是这样)
2.这种类型的扣除是否可以完成,但提案不允许这样做?如果是这样,为什么不呢?
3.如果这是非常模糊的,那么推断类型并尝试将其与明确的前向声明相匹配的一些例子会让你遇到麻烦吗?
4.这背后是否有更深层次的实施具体问题?
这只是一种疏忽吗?

小智 6

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

当编译器读取std::string some_function();它时,它会在二进制文件中创建一个引用它的位置,并说"这个函数是否被调用跳转到这个位置".

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

(Address offset)  (Symbol)
0x????????       std::string somefunction();
Run Code Online (Sandbox Code Playgroud)

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

现在,Function表看起来像这样......

(Address offset)  (Symbol)
0x????????       std::string somefunction();
0x????????       ????? somefunction();
Run Code Online (Sandbox Code Playgroud)

因此,当它找到返回类型时,它会将代码编译成二进制文件std::string.编译器现在知道返回类型是什么,因此它转到函数表并且也发生auto somefunction();了变化std::string somefunction();.

现在,Function表看起来像这样......

(Address offset)  (Symbol)
0x????????       std::string somefunction();
0x????????       std::string somefunction();
Run Code Online (Sandbox Code Playgroud)

现在编译器返回并继续编译该函数.一旦完成,它就会返回并完成vtable,只发现两次相同的符号.现在我们指的是哪个符号也很模糊.

那是什么原因呢?

不是100%肯定,但是在你的代码被足够下来以便允许进行演绎类型之前很久就会制作vtable.因此,编译器必须在该阶段使用的唯一选择是假设它是一个新符号.这只是我注意到整天看着符号表并编写自己的C++ 11编译器的东西.

然而,我绝不能说其他编译器,其中引入了大量的优化和其他步骤,我只是使用裸骨,但这是我对标准的理解.

最后一种类型是完全随意的.如果它们在扣除时不匹配则无关紧要.它永远不会那么遥远.问题出现在表中有两个相同的符号,并且您不能在返回类型上重载.