Variadic模板和复制构造函数

时间:2015-09-25 14:31:40

标签: c++ c++11 visual-studio-2013

为什么以下不编译:

struct a
{
    int i;
};


template <typename T>
class b
{
public:
    T mItem;


    template <typename... Arguments>
    b(Arguments&&... args) : mItem(std::forward<Arguments>(args)...)
    {
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    b<a>(1);

    return 0;
}
  

错误C2664:&#39; a :: a(const a&amp;)&#39; :无法从&#39; int&#39;转换参数1   到&#39; const a&amp;&#39;

但是只需添加一个像这样的额外参数就可以编译:

struct a
{
    int i;
};


template <typename T>
class b
{
public:
    T mItem;


    template <typename... Arguments>
    // just random extra argument
    b(int, Arguments&&... args) : mItem(std::forward<Arguments>(args)...)
    {
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    b<a>(1);

    return 0;
}

有没有比简单地为b的构造函数添加额外(无用)参数更简洁的方法?

3 个答案:

答案 0 :(得分:5)

您正在尝试依赖聚合初始化,但您需要使用大括号而不是括号来使用它:

template <typename... Arguments>
b(Arguments&&... args) : mItem{std::forward<Arguments>(args)...}
{
}

大括号意味着您正在使用列表初始化而不是值/直接初始化。当T是聚合类型时,前者解析为聚合初始化,但后两者不是。是的,C ++初始化规则很奇怪。

答案 1 :(得分:1)

在第一种情况下,您尝试调用

a(1)

你还没有。

在第二种情况下,1使用int参数,其余参数(即无)参数args。因此,您调用

a()

没关系。

请注意,在后一种情况下,您传递给1的{​​{1}}的值会丢失,并且不会像您预期的那样转发到b<a>::b

答案 2 :(得分:-1)

您正尝试使用int初始化A. A对int没有任何了解,A中没有构造函数可以做到这一点。当你提供一个额外的int参数时,你只是丢弃它而不是用空参数列表初始化A,调用默认构造函数。