无法在初始化时转换Type

Art*_*zuk 5 c++ templates c++11 list-initialization

我想我错过了什么,我不知道到底是什么.我们来看看代码片段.

template <typename T>
struct Foo { 
    Foo (int n, int p, string s, T t = {})
    : m_n {n}, m_p {p}, m_s {s}, m_t {t}
    {}

    const int m_n;
    const int m_p;
    const string m_s;
    T m_t;
};
Run Code Online (Sandbox Code Playgroud)

用法如下:

Foo<int> f_int1 {1, 2, "A", 155};
Foo<int> f_int2 {1, 2, "A"};
Run Code Online (Sandbox Code Playgroud)

一切都像预期的那样.但是当我想将用户定义的类型作为Foo的T参数时,会发生一些错误.考虑:

struct Boo {
    int z;
    int l;
};
Run Code Online (Sandbox Code Playgroud)

用法:

Foo<Boo> f_boo1 {1, 2, "A"};
Foo<Boo> f_boo2 {1, 2, "A", {1, 2}};
Run Code Online (Sandbox Code Playgroud)

这两条指令都给出了(gcc 4.8.1):

cannot convert ‘Boo’ to ‘int’ in initialization
Run Code Online (Sandbox Code Playgroud)

我可以像这样创建Boo对象:

Boo boo1 {};
Boo boo2 {1, 2};
Run Code Online (Sandbox Code Playgroud)

那么,你能告诉我问题出在哪里吗?

可能的方法:

struct Boo {
    Boo () : z {}, l {} {}
    Boo (int p1, int p2) : z {p1}, l {p2} {}

    int z;
    int l;
};
Run Code Online (Sandbox Code Playgroud)

以下说明均按预期工作:

Foo<Boo> f_boo1 {1, 2, "A"};
Foo<Boo> f_boo2 {1, 2, "A", {1, 2}};
Run Code Online (Sandbox Code Playgroud)

对我来说,没关系,我没有看到任何理由为什么不在课堂上添加两个构造函数,但是如果类型不是我的呢?我应该用构造函数编写简单的包装器吗?

谢谢,阿图尔

Bar*_*rry 6

那是因为您正在尝试执行聚合初始化Boo.见§8.5.4/ 3:

对象或类型引用的列表初始化T定义如下:

- 如果T是聚合,则执行聚合初始化(8.5.1).

你打算复制 - 构建你的Boo......但实际上你正在进行聚合初始化,这导致尝试int z从a 构造Boo,因此错误

错误:没有可行的从'Boo'到'int'的转换

请注意,您可以用更少的代码重复您的问题,而无需任何模板:

Boo b;
Boo b2{b}; // error
Run Code Online (Sandbox Code Playgroud)

修复很简单.只是不要使用列表初始化:

template <typename T>
struct Foo { 
    Foo (int n, int p, string s, T t = {})
    : m_n {n}, m_p {p}, m_s {s}, m_t(t)
    //                           ^^^^^^
{};
Run Code Online (Sandbox Code Playgroud)