Fra*_*nte 12 c++ inheritance decltype language-lawyer
我遇到了这段包含尾随返回类型和继承的代码片段。
以下最小示例可以使用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;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我们更改auto bar() -> decltype(foo(*this))为decltype(auto) bar()(c ++ 14扩展名),代码也会使用clang进行编译。链接到Godbolt https://godbolt.org/z/qf_k6X。
谁能解释我
auto bar() -> decltype(return expression)不同decltype(auto) bar()This is a gcc bug, the trailing return type isn't within a complete-class context [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
We see that a complete class is needed for the derived to base conversion from [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.
and [dcl.init.ref]
“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.
On the other hand, a function body is within a complete-class context and thus the derived to base conversion is well-formed. The return type involving a placeholder type (decltype(auto)) is valid as long as it is already deduced before an expression using it.
For a possible workaround in C++11, you may use
auto bar() -> decltype(foo(std::declval<Base&>()))
{
return foo(*this);
}
Run Code Online (Sandbox Code Playgroud)
provided you know that you want to call it with Base.
| 归档时间: |
|
| 查看次数: |
241 次 |
| 最近记录: |