2

在 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 会随着概念和要求的引入而改变吗?

4

2 回答 2

7

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

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

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

于 2015-05-17T18:10:59.680 回答
1

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

原因如下:模板是需要使用各种类型参数的通用代码。模板化代码中的某些操作可能对一种类型完全有效(如call_fon ),但对于另一种类型(如on )则A大错特错。标准中的决定是允许无意义的模板代码,例如for 类型,只要该模板函数从未使用过(这将触发模板函数的编译)。call_fBcall_fB

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

于 2015-05-17T18:10:24.720 回答