C++ 异构初始值设定项列表

C++ 异构初始值设定项列表,c++,c++17,initializer-list,C++,C++17,Initializer List,我有一个查询字段,并选择用于构造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{ al

我有一个查询字段,并选择用于构造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对象的需要

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));
    }
}
如果要保留复制/移动构造函数,必须过滤掉一些参数类型:

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)}...} {}

我试过做一次,甚至还问了一次,所以我猜。我敢肯定,在CPP中,异类init列表目前是不可能的。如果我错了,请纠正我,但您想要的是同构(相同类型)列表而不是异类(不同类型)列表。您使用的编译器是什么?对我来说似乎很好?或者我遗漏了什么?我想带可变模板的构造函数可能更好,但它隐藏了复制和移动构造函数。选择Select(其他)并选择Select(std::move(其他))停止编译。我将这两个构造函数都声明为默认值,但没有帮助。可能解决方案是使其不是构造函数,而是像MakeSelect(Args&&…fields)(如std::make_shared)这样的函数。是的,您必须过滤掉移动和复制构造函数。我编辑了答案
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)}...} {}
Select{
    QueryField{"up.audit_option" "option"},
    "uep.success",
    "uep.failure"
};