异构初始化列表
Heterogeneous initializer list
我有一个QueryField,选择用于构造SQL语句的助手类:
class QueryField
{
public:
QueryField(std::string_view column)
: m_column{ column }
{
}
QueryField(std::string_view column, std::string_view alias)
: m_column{ column }
, m_alias{ alias }
{
}
private:
std::string m_column;
std::string m_alias;
};
class Select
{
public:
Select(std::initializer_list<QueryField> fields)
{
for (auto & field : fields)
{
m_fields.emplace_back(std::move(field));
}
}
private:
std::vector<QueryField> m_fields;
};
从上面的代码中看到的是QueryField对象的集合,可以这样初始化:
Select{ QueryField{ "up.audit_option" "option" }, QueryField("uep.success"), QueryField("uep.failure") };
是否有可能消除明确指定QueryField的需求并以下初始化选择对象?
Select{ { "up.audit_option" "option" }, "uep.success", "uep.failure" };
使用解决方案,您确实可以放下类型,但是您必须保留牙套:
Select{ { "up.audit_option" "option" }, {"uep.success"}, {"uep.failure"} }
还要谨慎使用初始化列表:内部所有元素将被复制。即使您移动:
Select(std::initializer_list<QueryField> fields)
{
for (auto & field : fields)
{
// Actually copy. No move is done.
m_fields.emplace_back(std::move(field));
}
}
由于初始化器列表中的每个元素都是恒定的,因此不允许移动。
我首选的解决方案是删除std::initializer_list
,并使用简单的情况和更明确的情况使用复杂的情况。
为了允许真正的异源参数,我将使用variadic模板:
template<typename... Args>
Select(Args&&... fields) :
m_fields{QueryField{std::forward<Args>(args)}...} {}
如果要保留复制/移动构造函数,则必须过滤一些参数类型:
template<typename T, typename = void typename... Args>
struct is_not_copy_impl : std::false_type {};
template<typename T, typename Arg>
struct is_not_copy_impl<T, std::enable_if_t<std::is_base_of_v<T, std::decay_t<Arg>>>, Arg> : std::true_type {};
template<typename T, typename... Args>
using is_not_copy = is_not_copy_impl<T, void, Args...>;
template<typename... Args, std::enable_if_t<!is_not_copy<Select, Args...>::value>* = nullptr>
Select(Args&&... fields) :
m_fields{QueryField{std::forward<Args>(args)}...} {}
传递QueryField
时,此代码将移动,并在传递其他类型的值时构造新代码。
用法是:
Select{
QueryField{"up.audit_option" "option"},
"uep.success",
"uep.failure"
};
相关文章:
- 复制列表初始化的隐式转换的等级是多少
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 我使用向量来创建类对象列表.初始化向量时如何使用参数调用构造函数?
- C++11 中的混合列表初始化
- 我可以列表初始化 std::vector 并完美转发元素吗?
- 无法在声明时使用初始值设定项列表初始化常量字符*/字符串数组的向量
- C++20 从括号中的值列表初始化聚合,不支持内部数组
- 如何在向量列表初始化时避免对象复制以及如何延长临时的生存期
- 默认参数和空列表初始化
- 如何在列表初始化中放置额外的语句?
- C++列表初始化允许多个用户定义的转换
- 列表初始化是否将原子初始化为零
- 使用可变模板列表初始化数组,并放置new
- 使用整数初始化列表初始化长双精度的向量
- 直接列表初始化的自动规则
- 使用初始化列表初始化unique_ptr的容器,继续
- 如何修复"非聚合无法使用初始值设定项列表初始化" <map>
- 直接列表初始化和复制列表初始化之间的差异
- 为什么我可以在不使用赋值运算符的情况下使用列表初始化普通数组
- C++ - 使用类中的初始值设定项列表初始化动态集