具有无效成员函数的模板类

tml*_*len 2 c++ templates c++17

在C++中使用不能与其某些成员函数一起使用的类来实例化类模板是否合法?

例如:

class A {
public:
    void f() { }
};

class B {  
};

template<typename T>
class Wrapper {
private:
    T t_;
public:
    void call_f() { t_.f(); }
};

int main() {
    Wrapper<A> a;
    Wrapper<B> b;
    a.call_f();
}
Run Code Online (Sandbox Code Playgroud)

这段代码编译,我可以使用b,只要我不试图打电话b.call_f().(还显式实例化它template class Wrapper<B>;会导致编译错误,因为它会实例化所有成员函数.)

这是保证工作还是未定义的行为?如果是这样,那么随着概念和要求的引入,这将在C++ 17中发生变化吗?

Ker*_* SB 6

是的,总的来说.类模板的非虚拟成员函数本身就是函数模板,并且像所有函数模板一样,它们仅在使用时被实例化.因此,如果您从未使用类模板特化的某些成员函数,则成员函数无需对该特化有效.

从C++ 11开始,标准库实际上充分利用了这种细粒度的实例化控件.容器的类型要求适用于成员函数,而不是整个模板,因此例如,您可以在std::map<K, T>哪里使用T默认构造; 你就是不能打电话operator[]给它.

请注意,显式类模板实例化会实例化所有成员函数.