c++ - decltype 所需的不完整类型的派生到基转换

标签 c++ inheritance language-lawyer decltype

我遇到了这段涉及尾随返回类型和继承的代码。

以下最小示例使用 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.

[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.

另一方面,函数体位于完整类上下文中,因此派生到基类的转换是格式良好的。涉及占位符类型的返回类型 (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/

相关文章:

javascript - 在 QML Javascript 中调用 QCursor::setPos

python - 返回非实例化类类型的类型提示

c++ - std::optional 值的地址是否稳定?

c++ - boost 编程选项使我的应用程序崩溃

c# - 与从 C++ 到 C# 的内存映射文件共享链式结构

c++ - 如何以最简单的方式禁用 lua 中的风险函数?

javascript - AngularJS中范围原型(prototype)/原型(prototype)继承的细微差别是什么?

时间:: accessing parent class's events not possible?

C++ switch 语句表达式求值保证

c++ - 模板类型别名可见性编译器不一致