为什么 auto return 类型推导适用于未完全定义的类型?

Why does auto return type deduction work with not fully defined types?

考虑以下几点:

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();
}

我想根据派生 class 中 operator() 的签名,使用 return 类型在 CRTP 基 class 中创建一个成员函数。但是 decltype(&Der::operator()) 编译失败; Foo 中的 operator() 成员函数不可见。我认为这是因为基础 class 模板在 Foo 完全定义之前实例化了。

令人惊讶的是,如果我为 return 类型放置 auto,它会编译。我假设 auto 会使编译器从函数体中推断出 return 类型并失败 - 因为函数体使用未完全定义的 Foo 类型。

此行为对于 MSVC 2015.3 和 Clang 3.8 都是相同的

为什么代码开始与 auto 一起工作? auto 类型推导是否以某种方式 "delay" 实例化?或者使用不同于手写 return 类型表达式的上下文?

你猜对了。推导的 return 类型在需要函数签名之前不会被实际推导。这意味着它将在调用 getCallOperator 的上下文中推导,此时 Foo 已完全定义。

这是在 7.1.6.4p12 中指定的:

Return type deduction for a function template with a placeholder in its declared type occurs when the definition is instantiated even if the function body contains a return statement with a non-type-dependent operand.