无法在初始化中转换类型

Cannot convert Type in initialization

本文关键字:转换 类型 初始化      更新时间:2023-10-16

我想我错过了一些东西,我不知道到底是什么。让我们看一下代码片段。

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;
};

用法如下所示:

Foo<int> f_int1 {1, 2, "A", 155};
Foo<int> f_int2 {1, 2, "A"};

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

struct Boo {
    int z;
    int l;
};

和用法:

Foo<Boo> f_boo1 {1, 2, "A"};
Foo<Boo> f_boo2 {1, 2, "A", {1, 2}};

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

cannot convert ‘Boo’ to ‘int’ in initialization

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

Boo boo1 {};
Boo boo2 {1, 2};

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

可能的解决方案:

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

以下两个说明都按预期工作:

Foo<Boo> f_boo1 {1, 2, "A"};
Foo<Boo> f_boo2 {1, 2, "A", {1, 2}};

对我来说,没关系,我看不出有什么理由不向类中添加两个构造函数,但是如果类型不是我的怎么办?我应该用构造函数编写简单的包装器吗?

谢谢阿图尔

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

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

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

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

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

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

Boo b;
Boo b2{b}; // error

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

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)
    //                           ^^^^^^
{};