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

Template class with invalid member functions

本文关键字:函数 无效 成员      更新时间:2023-10-16

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

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

这是保证工作还是它是未定义的行为?如果是这样,在c++ 17中会随着概念和需求的引入而改变吗?

一般来说是的。类模板的非虚成员函数本身就是函数模板,和所有函数模板一样,它们只有在使用时才被实例化。因此,如果您从不使用类模板特化的某些成员函数,则成员函数不必对该特化有效。

从c++ 11开始,标准库实际上充分利用了这种细粒度的实例化控制。容器的类型要求适用于成员函数,而不是整个模板,因此,例如,你可以有一个std::map<K, T>,其中T不是默认可构造的;你不能在它上面调用operator[]

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

这是标准行为,不会改变。

原因如下:模板是需要处理各种类型参数的泛型代码。模板化代码中的一些操作可能对一种类型完全有效(如call_fA),但对另一种类型却完全错误(如call_fB)。标准中做出的决定是允许无意义的模板代码,例如B类型的call_f,只要这个模板函数从不被使用(这会触发模板函数的编译)。

这样,代码就可以是通用的并且安全的,因为这些检查是在编译时完成的。