如何在类模板中实例化含任意构造函数签名的typename对象
实现方案
完全可以,C++11引入的可变参数模板和完美转发特性就是为了解决这类问题的,可以把类构造函数接收的参数原封不动转发给模板类型T的构造函数,支持任意数量、任意类型的参数传入,适配T的任意构造函数签名。
以下是修正后的可运行实现:
#include <vector> #include <utility> // 用于std::forward template<typename T> class A { public: // 可变参数模板构造函数,支持匹配任意数量、任意类型的入参 template<typename... Args> A(Args&&... args); private: std::vector<T> vec; }; template<typename T> template<typename... Args> A<T>::A(Args&&... args) { vec.reserve(10); // 预先分配空间优化性能 for(size_t i = 0; i < 10; ++i) { // 完美转发参数给T的构造函数,原地构造对象避免额外拷贝开销 vec.emplace_back(std::forward<Args>(args)...); } }
核心细节说明
- 用
template<typename... Args>声明可变参数模板,能匹配任意数量、任意类型的输入参数,不需要提前限定构造函数的参数列表 std::forward<Args>(args)实现完美转发,会保留参数的左值/右值属性,既能避免不必要的拷贝,也能适配接收右值引用参数的T构造函数- 用
emplace_back代替push_back,可以直接在vector的内存空间上原地构造T对象,不需要额外生成临时对象再拷贝/移动,性能更优
使用示例
哪怕是构造函数签名完全不同的类型,都可以直接用该模板实例化:
#include <string> // 无参构造类型 class Test1 {}; // 需要两个入参的构造类型 class Test2 { public: Test2(int a, std::string b) : m_a(a), m_b(std::move(b)) {} private: int m_a; std::string m_b; }; int main() { A<Test1> a1; // 自动匹配Test1的无参构造,生成10个Test1对象 A<Test2> a2(10, "demo"); // 自动转发参数给Test2的构造函数,生成10个Test2对象 return 0; }
注意事项
该实现要求所有传入的参数对T的构造函数都是合法的,如果参数不匹配会在编译期直接报错,符合C++静态类型检查的特性。如果需要支持不同实例传入不同参数构造T对象,可以额外提供单独插入元素的接口,逻辑和构造函数一致,用可变参数+完美转发即可实现。
内容的提问来源于stack exchange,提问作者Aisec Nory
相关产品推荐
相关产品推荐

