与引用匹配的 C++ 模板类型 [重复]

c++ template type matching with references [duplicate]

提问人:wenxi wang 提问时间:11/17/2023 最后编辑:wenxi wang 更新时间:11/17/2023 访问量:74

问:

当我运行以下代码时,发生错误。

#include <iostream>
using namespace std;

class M {
 public:
  M(): a(0), b(0) {}
  M(int a, int b): a(a), b(b) {}
 private:
  int a;
  int b;
};

template <typename T>
class Test {
 public:
  Test(const T& my) { }
  T my_;
};

template <typename T>
using ReferTest = Test<T&>;

int main()
{
   ReferTest<M> t2(M(3,4));
}

错误是:

main.cpp: In function ‘int main()’:
main.cpp:25:20: error: cannot bind non-const lvalue reference of type ‘M&’ to an rvalue of type ‘M’
   25 |    ReferTest<M> t2(M(3,4));
      |                    ^~~~~~
main.cpp:16:17: note:   initializing argument 1 of ‘Test<T>::Test(const T&) [with T = M&]’
   16 |   Test(const T& my) { }
      |        ~~~~~~~~~^~

“无法将类型为'M&'的非常量左值引用绑定到类型为'M'的右值”让我感到困惑,我知道M(3,4)是一个右值,但是Test构造函数中的类型是“const T&”,而不是“non-const”。

C++ 模板

评论

1赞 wenxi wang 11/17/2023
谢谢,我会学习它并修改我的question.@Yunnosch
0赞 n. m. could be an AI 11/17/2023
你试着用 代替 ,你会得到 “reference to (const T)”,其中 T 是对 M 的引用。但是引用本身从来都不是常量,所以这个常量被丢弃了。const T&T=M&
1赞 StoryTeller - Unslander Monica 11/17/2023
另一个“领先常量具有误导性”的案例。我不是在开玩笑,如果你改用,并按照 n.m. 建议的替代方法进行操作,问题就变得显而易见了。T const&
0赞 Jerry Coffin 11/17/2023
仔细看这里:看看你是否在某处没有看到丢失的地方。当你解决这个问题时,它仍然不会编译(你需要初始化它才能编译)。template <typename T> using ReferTest = Test<T&>;constTest::my_
1赞 molbdnilo 11/17/2023
相同情况的一个稍小的例子:。Test<int&> t2(1);

答:

0赞 Pepijn Kramer 11/17/2023 #1

我认为您应该在模板中使用转发引用,而不是像这样的 const&,然后复制临时引用。使用像您这样的临时对象的引用充其量是棘手的。

#include <iostream>

// don't use using namespace std;

class M 
{
 public:
  M(): a(0), b(0) {}
  M(int a, int b): a(a), b(b) {}

  ~M(){ std::cout << "deleting M\n"; }
  int get_a() const noexcept { return a; };

 private:
  int a;
  int b;
};

template <typename T>
class Test {
 public:
  Test(T&& my) : // <== forwarding here
  my_{std::forward<T>(my) } 
  {
  }

  T my_;
};

template <typename T>
using ReferTest = Test<T>; // <== no reference here!

int main()
{
    ReferTest<M> t2(M{3,4}); // <== M's temporary will be deleted after this line! So it is not safe to have a reference to it after this line.
    std::cout << t2.my_.get_a();
}