我遇到了这段涉及尾随返回类型和继承的代码。
以下最小示例使用 g++ 编译良好,而不是 clang
struct Base {};
int foo(Base&) {
return 42;
}
struct Derived : public Base {
auto bar() -> decltype(foo(*this)) {
return foo(*this);
}
};
int main()
{
Derived derived;
derived.bar();
return 0;
}
但是,如果我们将 auto bar() -> decltype(foo(*this))
更改为 decltype(auto) bar()
(c++14 扩展),代码也用 clang 编译。神 bolt 链接 https://godbolt.org/z/qf_k6X .
谁能解释一下
auto bar() -> decltype(return expression)
与decltype(auto) bar() 的区别
- 为什么编译器之间的行为不同
- 正确的实现方式是什么?
最佳答案
这是一个 gcc 错误,尾随返回类型不在 完整类上下文中 [class.mem]
A complete-class context of a class is a
- function body,
- default argument,
- noexcept-specifier ([except.spec]),
- contract condition, or
- default member initializer
我们看到从[conv.ptr] 派生到基类的转换需要一个完整的类。
A prvalue of type “pointer to cv D”, where D is a complete class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class of D.
“cv1 T1” is reference-compatible with “cv2 T2” if a prvalue of type “pointer to cv2 T2” can be converted to the type “pointer to cv1 T1” via a standard conversion sequence. In all cases where the reference-compatible relationship of two types is used to establish the validity of a reference binding and the standard conversion sequence would be ill-formed, a program that necessitates such a binding is ill-formed.
另一方面,函数体位于完整类上下文中,因此派生到基类的转换是格式良好的。涉及占位符类型的返回类型 (decltype(auto)
) is valid只要它在使用它的表达式之前已经推导出来。
对于 C++11 中可能的解决方法,您可以使用
auto bar() -> decltype(foo(std::declval<Base&>()))
{
return foo(*this);
}
如果你知道你想用 Base
来调用它。
关于c++ - decltype 所需的不完整类型的派生到基转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55860264/