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

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

问题描述:

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

Is it legal in C++ to have instantiate class templates with classes that do not work with some of its member functions?

例如:

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&gt ;; 实例化它会导致编译错误,因为它实例化了所有成员函数。)

This code compiles, and I can use b, as long as I don't try to call b.call_f(). (Also explicitly instantiating it with template class Wrapper<B>; causes a compilation error because that instantiates all member functions.)

这是否可以保证正常工作还是不确定的行为?
如果是这样,是否会在C ++ 17中通过引入概念和要求来进行更改?

Is this guaranteed to work or is it undefined behavior? If so, will this change in C++17 with the introduction of concepts and requirements?

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

Yes, in general. Non-virtual member functions of class templates are themselves function templates, and like all function templates they only get instantiated when used. So if you never use some member function of a class template specialization, member function need not be valid for that specialization.

自C ++ 11起,标准库实际上使充分利用此细粒度的实例化控件。容器的类型要求适用于成员函数,而不适用于整个模板,因此例如,您可以具有 std :: map< K,T> 其中 T 不是默认可构造的;您只是不能调用 operator []

Since C++11, the standard library actually makes ample use of this fine-grained instantiation control. Type requirements for containers apply to member functions, not to the entire template, so for example you can have an std::map<K, T> where T is not default-constructible; you just cannot call operator[] on it.

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

Note that explicit class template instantiation instantiates all the member functions.