导入重度模板化基类构造函数时如何避免模板冗余
问题:避免继承模板化std::variant时的构造函数导入冗余
我想知道有没有方法可以避免导入基类构造函数时出现大量模板冗余代码。以下是一个继承自模板化std::variant的示例:
template <typename StringType, typename Allocator> class JSON : public std::variant<std::monostate, std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>, std::vector<JSON<StringType, Allocator>, Allocator>, bool, double, StringType> { public: using std::variant<std::monostate, std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>, std::vector<JSON<StringType, Allocator>, Allocator>, bool, double, StringType>::variant; };
可以看到代码里有大量重复的模板参数,可读性差且容易出错。我之前听说模板类中可以省略部分参数让编译器自动推导,但尝试using variant::variant并没有效果。本质上就是想避免重复编写这些冗余的模板代码,希望得到解决思路或提示。
解决方案
核心思路是通过定义别名简化重复的基类模板实例化代码,避免多次书写冗长的模板参数列表:
方法1:类内部定义基类别名
在JSON类内部先定义基类的别名,后续继承和导入构造函数都使用这个别名:
template <typename StringType, typename Allocator> class JSON : public std::variant< std::monostate, std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>, std::vector<JSON<StringType, Allocator>, Allocator>, bool, double, StringType> { private: // 定义基类别名,将冗长的模板实例化封装起来 using Base = std::variant< std::monostate, std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>, std::vector<JSON<StringType, Allocator>, Allocator>, bool, double, StringType>; public: // 通过别名导入基类构造函数,代码简洁且不易出错 using Base::variant; };
方法2:类外部定义模板别名
把基类的模板实例化提取为外部的模板别名,进一步提升代码复用性:
// 外部定义模板别名,集中维护基类的模板参数 template <typename StringType, typename Allocator> using JSONVariantBase = std::variant< std::monostate, std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>, std::vector<JSON<StringType, Allocator>, Allocator>, bool, double, StringType>; template <typename StringType, typename Allocator> class JSON : public JSONVariantBase<StringType, Allocator> { public: // 直接使用外部别名导入构造函数 using JSONVariantBase<StringType, Allocator>::variant; };
为什么using variant::variant无效?
因为你继承的是std::variant的具体实例化版本,而非std::variant模板本身。直接写variant::variant会被编译器解析为std::variant模板的构造函数,无法匹配当前继承的那个特定实例的构造函数,因此必须明确指定实例化后的基类类型。
内容的提问来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

