【问题标题】:Why can't I create a temporary of this templated class with an lvalue constructor argument?为什么我不能使用左值构造函数参数创建这个模板类的临时对象?
【发布时间】:2021-07-04 20:57:03
【问题描述】:

对于我的生活,我似乎无法创建这个类的临时,为什么不允许我这样做?

template <typename T>
struct Dog
{
    Dog(T t) : tag(t) {}
    T tag; 
};

int main()
{
    int tag = 6;
    Dog<int>(6); // Works fine
    Dog<int>(tag); // On Visual Studio I get no default constructor exists for class Dog<int>
                  // On onlineGDB I get error: no matching function for call to ‘Dog::Dog()’
}

另外,右值和左值有什么区别:

Dog(6); // Deduces fine
Dog(tag); // Deduction fail, error: missing template arguments before ‘(’ token

还有:

Dog<int>{tag}; // Works. 

我接受它是因为这是聚合初始化?

【问题讨论】:

    标签: c++ templates most-vexing-parse


    【解决方案1】:

    Dog(6);Dog&lt;int&gt;(6); 声明临时的Dog&lt;int&gt;s,用值 6 构造。模板参数推导在第一种情况下工作正常,而模板参数在第二种情况下是显式的。

    但是,Dog(tag);不是创建一个临时的。它是Dog&lt;?&gt; 类型的变量tag 的声明符。一般来说,括号是多余的,即 int xint (x)int ((x)) 都是等价的。在这种情况下,错误是您没有给出一个初始化器来推断Dog 的模板参数。另一个错误是在进行类模板参数推导的声明符周围不能有括号。

    Dog&lt;int&gt;(tag); 类似,它是Dog&lt;int&gt; 类型的变量tag 的声明符。由于参数是显式的,所以不需要做推演,但是这里的错误是你没有Dog的默认构造函数,而且你自己也没有为构造函数提供参数。

    Dog{tag}; 没有与括号相同的问题。它声明了一个临时的Dog,如您所料,使用tag 构造。

    【讨论】:

      【解决方案2】:

      由于C++解析规则,

      Dog<int>(tag);
      

      等价于

      Dog<int> tag;
      

      引入大括号初始化以避免这些解析歧义:

      Dog<int>{tag};
      

      【讨论】:

        猜你喜欢
        • 2013-09-23
        • 1970-01-01
        • 2022-10-20
        • 2021-09-25
        • 2020-03-06
        • 1970-01-01
        • 1970-01-01
        • 2019-09-04
        • 2021-06-30
        相关资源
        最近更新 更多