提问人:glades 提问时间:4/14/2023 最后编辑:Evgglades 更新时间:4/14/2023 访问量:83
在导入大量模板化基类的基类构造函数时避免模板混乱
Avoid template mess when importing base class constructors of heavily templated base class
问:
这只是一个简短的询问,如果有可能以某种方式导入基类构造函数,而没有所有的模板膨胀。考虑这个例子,我从模板化继承: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
答:
3赞
TartanLlama
4/14/2023
#1
您可以编写一个别名模板来消除一些重复:
template <template <class...> class Temp, class StringType, class Allocator>
using variant_for = std::variant<std::monostate,
std::unordered_map<StringType, Temp<StringType, Allocator>, std::hash<Temp<StringType, Allocator>>, std::equal_to<StringType>, Allocator>,
std::vector<Temp<StringType, Allocator>, Allocator>,
bool,
double,
StringType>;
template <typename StringType, typename Allocator>
class JSON : public variant_for<JSON, StringType, Allocator>
{
public:
using variant_for<JSON, StringType, Allocator>::variant;
};
0赞
MSalters
4/14/2023
#2
快速构思:使用继承来继承该名称
template <typename StringType, typename Allocator>
class JSONbase
{
public:
using JSONStr = JSON<StringType, Allocator>;
using variant = std::variant<std::monostate,
std::unordered_map<StringType, JSONStr, std::hash<JSONStr>, std::equal_to<StringType>, Allocator>,
std::vector<JSONStr, Allocator>,
bool,
double,
StringType>::variant;
}
template <typename StringType, typename Allocator>
class JSON :
public JSONbase<StringType, Allocator>,
public typename JSONbase<StringType, Allocator>::variant
{
using variant::variant;
};
7赞
Evg
4/14/2023
#3
非限定查找不会找到基类中注入的类名,因为基类是依赖于派生类的模板参数的模板。让我们限定该名称:
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 MyBase = typename JSON::variant;
public:
using MyBase::MyBase;
};
评论
0赞
TartanLlama
4/14/2023
@OP我建议接受这个答案而不是我的答案,除非这是你到处使用的模式
0赞
glades
4/14/2023
这!我一直在寻找这个。那你还不如做恰到好处呢?using JSON::variant::variant
1赞
Evg
4/14/2023
@glades MSVC 不接受 .为了清楚起见,我自己的偏好是添加一个别名。using JSON::variant::variant;
0赞
Red.Wave
4/15/2023
终于一个理智的解决方案了!虽然这个问题是重复的。我不会投票结束,因为这个很好的答案。
评论
using base_t = your_big_type; using base_t::base_t;