为什么自动返回类型推导与未完全定义的类型一起工作?

Mic*_*zyk 39 c++ crtp return-type-deduction c++14

考虑以下:

template<typename Der>
struct Base {
    // NOTE: if I replace the decltype(...) below with auto, code compiles
    decltype(&Der::operator()) getCallOperator() const {
        return &Der::operator();
    }
};

struct Foo : Base<Foo> {
    double operator()(int, int) const {
        return 0.0;
    }
};

int main() {
    Foo f;
    auto callOp = f.getCallOperator();
}
Run Code Online (Sandbox Code Playgroud)

我想在CRTP基类中创建一个成员函数,其返回类型取决于operator()派生类中的签名.但decltype(&Der::operator())无法编译; 将operator()在成员函数Foo是不可见的.我假设这是因为基类模板在Foo完全定义之前被实例化.

令人惊讶的是,如果我auto为返回类型放置它编译.我假设这auto会使编译器从函数体中推导出返回类型并失败 - 因为正文使用了未完全定义的Foo类型.

MSVC 2015.3和Clang 3.8的行为相同

为什么代码开始使用auto?难道auto类型推演莫名其妙"延迟"的实例?或者使用与手写返回类型表达式不同的上下文?

Seb*_*edl 24

你的猜测是正确的.在需要函数签名之前,实际上不推导推导出的返回类型.这意味着它将在调用的上下文中推断出getCallOperator,此时Foo完全定义.

这在7.1.6.4p12中指定:

当实例化定义时,即使函数体包含带有非类型相关操作数的return语句,也会在其声明类型中使用占位符的函数模板返回类型推导.