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

Template class with invalid member functions

在 C++ 中用 class 实例化 class 模板是否合法,这些模板不适用于其某些成员函数?

例如:

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 是否会随着概念和要求的引入而发生变化?

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

原因如下:模板是需要处理各种类型参数的通用代码。模板代码中的某些操作可能对一种类型完全有效(如 call_fA 上),但对另一种类型则非常错误(如 call_fB 上)。标准中做出的决定是允许无意义的模板代码,例如类型 Bcall_f,只要从未使用过此模板函数(这将触发模板函数的编译) .

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

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

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

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