简体   繁体   English

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

[英]Template class with invalid member functions

Is it legal in C++ to have instantiate class templates with classes that do not work with some of its member functions? 在C ++中使用不能与其某些成员函数一起使用的类来实例化类模板是否合法?

For example: 例如:

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

This code compiles, and I can use b , as long as I don't try to call b.call_f() . 这段代码编译,我可以使用b ,只要我不尝试调用b.call_f() (Also explicitly instantiating it with template class Wrapper<B>; causes a compilation error because that instantiates all member functions.) (还使用template class Wrapper<B>;显式实例化它template class Wrapper<B>;导致编译错误,因为它实例化了所有成员函数。)

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? 如果是这样,那么随着概念和要求的引入,这将在C ++ 17中发生变化吗?

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. 因此,如果您从未使用类模板特化的某些成员函数,则成员函数无需对该特化有效。

Since C++11, the standard library actually makes ample use of this fine-grained instantiation control. 从C ++ 11开始,标准库实际上充分利用了这种细粒度的实例化控件。 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; 容器的类型要求适用于成员函数,而不是整个模板,因此例如,您可以使用std::map<K, T> ,其中T不是默认构造的; you just cannot call operator[] on it. 你就是不能在它上面调用operator[]

Note that explicit class template instantiation instantiates all the member functions. 请注意,显式类模板实例化会实例化所有成员函数。

This is standard behavior and will not change. 这是标准行为,不会改变。

The reason is the following: Templates are generic code that needs to work with various type arguments. 原因如下:模板是需要使用各种类型参数的通用代码。 Some operations in templated code may be perfectly valid for one type (as call_f on A ), but horribly wrong for another (as call_f on B ). 模板化代码中的某些操作对于一种类型(如call_fA call_f )可能完全有效,但对另一种类型则非常错误(如B call_f )。 The decision made in the standard was to allow non-sensical template code, such as the call_f for type B , as long as this template function is never used (which would trigger compilation of the template function). 标准中的决定是允许非敏感模板代码,例如类型Bcall_f ,只要从不使用此模板函数(这将触发模板函数的编译)。

That way, code can be generic and also safe, because these checks are done at compile time. 这样,代码可以是通用的,也是安全的,因为这些检查是在编译时完成的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM