对于构造函数,如何在variadic-templates和std :: initializer_list之间进行选择?

kfm*_*e04 11 c++ templates initializer-list variadic-templates c++11

在c ++ 11的当前状态(比如gcc 4.7.2)中,我应该如何选择使用variadic-template还是std::initializer_list需要可以接受变量参数的构造函数?

And*_*owl 15

可变参数模板允许您提供不同类型的参数,而使用参数类型进行std::initializer_list模板化.这意味着列表中所有元素的类型必须相同(或可转换为基础类型,但不允许缩小转换).根据您是否需要,您可以选择其中一个.

此外,如果您需要完美转发,则可变参数模板通常是默认选项,因为语法形式T&&可以绑定到左值引用和右值引用,而类似的类型推导不能执行initializer_list:

struct A
{
    // Deduces T& for lvalue references, T for rvalue references, and binds to both
    template<typename... Ts>
    A(Ts&&...) { }

    // This is an rvalue reference to an initializer_list. The above type deduction
    // does not apply here
    template<typename T>
    A(initializer_list<T>&&) { }
};
Run Code Online (Sandbox Code Playgroud)

另请注意,initializer_list当您使用统一初始化语法(即花括号)时,默认情况下将调用接受an的构造函数,即使存在另一个可行的构造函数.这可能是也可能不是您希望拥有的东西:

struct A
{
    A(int i) { }
};

struct B
{
    B(int) { }
    B(std::initializer_list<A>) { }
};

int main()
{
    B b {1}; // Will invoke the constructor accepting initializer_list
}
Run Code Online (Sandbox Code Playgroud)

  • 扩展关于完美转发的一点,`std :: initializer_list <T> :: reference`(例如`*l.begin()`的结果类型)是`T const&`,它禁止移动.您可以将仅移动值放入,但不能移出它们. (3认同)