具有未定义成员函数返回类型的模板实例化

tml*_*len 4 c++ templates auto c++11 c++14

struct Value {
    using a_type = int;
    a_type f() { return 1; }
};

template<typename T>
struct Wrapper {
    T t;
    auto call_f() { return t.f(); }
};

int main() {
    Wrapper<Value> w;
    Wrapper<int> w2;
    w.call_f();
}
Run Code Online (Sandbox Code Playgroud)

这对Clang和GCC很好.Wrapper<int>即使返回类型Wrapper<int>::call_f()无法推断(没有int::f()),也会被实例化.只有在w2.call_f()被调用时它才会失败.

这是C++标准的一部分,是否可以在所有编译器上运行?

Tar*_*ama 11

是的,这是C++标准的一部分.

模板实例化的规则冗长而复杂,但简短版本是模板类的成员函数仅在需要时实例化.如果没有任何东西调用它,或者尝试获取它的指针,或者显式地实例化它(可能还有一些我忘记的其他情况),那么它就不会被实例化并且你的代码格式正确.

正如@dyp指出的那样,它只是在实例化类定义时实例化的成员函数的声明([temp.inst]/1),但返回类型推导仅在实例化函数定义时执行([dcl.spec.auto]/12).

这对于最小化模板开销和允许类型要求非常有用.这个功能可以让你做到这样的事情:

struct Foo {
    //no default constructor
    Foo(int);
};

std::vector<Foo> foos;
Run Code Online (Sandbox Code Playgroud)

某些std::vector函数(resize例如)需要T是可默认构造的,但只要您不调用这些函数,您仍然可以使用其他函数std::vector.