【问题标题】:Variadic template and copy constructors可变模板和复制构造函数
【发布时间】:2015-09-25 22:53:49
【问题描述】:

为什么下面的代码不能编译:

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: 'a::a(const a &)' : 无法从 'int' 转换参数 1 到 'const a &'

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

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 的构造函数添加一个额外的(无用的)参数更简洁的方法?

【问题讨论】:

  • 因为值初始化、聚合初始化和所有的爵士乐。

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


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    a(1)
    

    你没有。

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

    a()
    

    没关系。

    请注意,在后一种情况下,您传递给b&lt;a&gt;::b1 的值会丢失,并且不会像您预期的那样转发给a::i

    【讨论】:

      【解决方案3】:

      您正在尝试用 int 初始化 A。 A 对 int 一无所知,A 中没有构造函数可以做到这一点。当您提供额外的 int 参数时,您只是将其丢弃,然后使用空参数列表初始化 A,调用默认构造函数。

      【讨论】:

      • 这个答案掩盖了值初始化的极其重要的影响。
      猜你喜欢
      • 2016-09-12
      • 2016-09-02
      • 2011-05-24
      • 1970-01-01
      • 2016-01-02
      • 2021-08-31
      • 1970-01-01
      • 2016-03-22
      • 1970-01-01
      相关资源
      最近更新 更多