使用LVALUE参考时Sfinae,但使用RVALUE REF时成功

发布于 2025-02-07 11:55:04 字数 589 浏览 0 评论 0原文

我搜索了,但实际上找不到答案,为什么只有在Lvalue Ref通过论点时会发生Sfinae,但是当Rvalue Ref通过ARG时,构建成功:

template <typename T>
class A {
 public:
  using member_type = T;
};

template <typename AType>
typename AType::member_type f(AType&& m) {
  typename AType::member_type res{};
  return res;
}

void demo() {
  A<int> a;

  // ERROR: candidate template ignored: substitution failure 
  // [with AType = A<int> &]: type 'A<int> &' 
  // cannot be used prior to '::' because it has no members
  f(a); 

  // BUILD SUCCESS
  f(std::move(a)); 
}

I searched but really couldn't find an answer why SFINAE happens only when the argument is passed by lvalue ref, but the build succeeds when the arg is passed by rvalue ref:

template <typename T>
class A {
 public:
  using member_type = T;
};

template <typename AType>
typename AType::member_type f(AType&& m) {
  typename AType::member_type res{};
  return res;
}

void demo() {
  A<int> a;

  // ERROR: candidate template ignored: substitution failure 
  // [with AType = A<int> &]: type 'A<int> &' 
  // cannot be used prior to '::' because it has no members
  f(a); 

  // BUILD SUCCESS
  f(std::move(a)); 
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

裸钻 2025-02-14 11:55:04

当您拥有

template <typename AType>
typename AType::member_type f(AType&& m)

所谓的转发参考时。即使它看起来像是RVALUE参考,此参考类型也可以与LVALUES或RVALUE绑定。它的工作方式是,当您将lvalue传递给fatype被推荐为t&amp;,而当您传递rvalueAtype 仅推荐为t

因此,当您进行f(a); atype被推导为a&lt; int&gt;&amp;,然后尝试形成返回类型a&lt; int&gt; :: member_type无效,因为参考没有类型成员。

相反,当您执行F(std :: Move(a));, atype 被推荐为a&lt; int&gt; and code> and a&lt ; int&gt;确实具有member_type类型成员。

要解决此问题,您可以使用 std :::::::: decay_t 喜欢

template <typename AType>
auto f(AType&& m) {
  typename std::decay_t<AType>::member_type res{};
  return res;
}

When you have

template <typename AType>
typename AType::member_type f(AType&& m)

You have what is called a forwarding reference. Even though it looks like an rvalue reference, this reference type can bind to lvalues or rvalues. The way it works is when you pass an lvalue to f, AType gets deduced to being T&, and when you pass an rvalue AType gets deduced to just T.

So, when you do f(a); AType gets deduced as A<int>&, and you try to form the return type of A<int>&::member_type which is invalid as references do not have type members.

Conversely when you do f(std::move(a));, AType gets deduced to A<int> and A<int> does have a member_type type member.

To fix this you can remove the reference-ness of type by using std::decay_t like

template <typename AType>
auto f(AType&& m) {
  typename std::decay_t<AType>::member_type res{};
  return res;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文