具有无效成员函数的模板 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_f
在 A
上),但对另一种类型则非常错误(如 call_f
在 B
上)。标准中做出的决定是允许无意义的模板代码,例如类型 B
的 call_f
,只要从未使用过此模板函数(这将触发模板函数的编译) .
这样,代码就可以是通用的并且也是安全的,因为这些检查是在编译时完成的。
是的,一般来说。 class 模板的非虚拟成员函数本身就是函数模板,和所有函数模板一样,它们只有在使用时才会被实例化。因此,如果您从不使用 class 模板特化的某些成员函数,则成员函数不必对该特化有效。
从 C++11 开始,标准库实际上充分利用了这种细粒度的实例化控制。容器的类型要求适用于成员函数,而不是整个模板,因此例如你可以有一个 std::map<K, T>
其中 T
不是默认构造的;你不能在上面调用 operator[]
。
请注意,显式 class 模板实例化会实例化所有成员函数。
在 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_f
在 A
上),但对另一种类型则非常错误(如 call_f
在 B
上)。标准中做出的决定是允许无意义的模板代码,例如类型 B
的 call_f
,只要从未使用过此模板函数(这将触发模板函数的编译) .
这样,代码就可以是通用的并且也是安全的,因为这些检查是在编译时完成的。
是的,一般来说。 class 模板的非虚拟成员函数本身就是函数模板,和所有函数模板一样,它们只有在使用时才会被实例化。因此,如果您从不使用 class 模板特化的某些成员函数,则成员函数不必对该特化有效。
从 C++11 开始,标准库实际上充分利用了这种细粒度的实例化控制。容器的类型要求适用于成员函数,而不是整个模板,因此例如你可以有一个 std::map<K, T>
其中 T
不是默认构造的;你不能在上面调用 operator[]
。
请注意,显式 class 模板实例化会实例化所有成员函数。