存在完善的转发构造函数时,按左值引用构造函数的意图是什么? [英] What's the intention of forward-by-lvalue-reference constructor while a perfect forwarding constructor exists?

查看:88
本文介绍了存在完善的转发构造函数时,按左值引用构造函数的意图是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们以std::pair<T1, T2>为例.它具有以下两个构造函数:

Let's take std::pair<T1, T2> as an example. It has the following two constructors:

constexpr pair( const T1& x, const T2& y );                      // #1
template< class U1, class U2 > constexpr pair( U1&& x, U2&& y ); // #2

似乎#2可以处理#1可以处理的所有情况(而不会降低性能),但参数是列表初始化器的情况除外.例如,

It seems that #2 can handle all cases that #1 can handle (without worse performance), except for cases where an argument is a list-initializer. For example,

std::pair<int, int> p({0}, {0}); // ill-formed without #1

所以我的问题是:

  • 如果#1仅用于list-initializer参数,由于xy最终绑定到从list-initializers初始化的临时对象,为什么不使用constexpr pair( T1&& x, T2&& y );呢?

  • If #1 is only intended for list-initializer argument, since x and y finally bind to temporary objects initialized from list-initializers, why not use constexpr pair( T1&& x, T2&& y ); instead?

否则,#1的实际意图是什么?

Otherwise, what's the actual intention of #1?

推荐答案

如果要存储的对象是临时对象但不能移动,该怎么办?

What if the object you want to store is a temporary one but is not movable ?

#include <type_traits>
#include <utility>
#include <iostream>

class   test
{
public:
  test() { std::cout << "ctor" << std::endl; }
  test(const test&) { std::cout << "copy ctor" << std::endl; }
  test(test&&) = delete; // { std::cout << "move ctor" << std::endl; }
  ~test() { std::cout << "dtor" << std::endl; }

private:
  int dummy;
};

template <class T1, class T2>
class   my_pair
{
public:
  my_pair() {}
  // Uncomment me plz !
  //my_pair(const T1& x, const T2& y) : first(x), second(y) {}
  template <class U1, class U2, class = typename std::enable_if<std::is_convertible<U1, T1>::value && std::is_convertible<U2, T2>::value>::type>
  my_pair(U1&& x, U2&& y) : first(std::forward<U1>(x)), second(std::forward<U2>(y)) {}

public:
  T1 first;
  T2 second;
};

int     main()
{
  my_pair<int, test>    tmp(5, test());
}

上面的代码无法编译,因为my_pair的所谓完美"转发构造函数将临时的test对象作为右值引用转发,而后者又试图调用test显式删除的move构造函数.

The above code doesn't compile because the so called "perfect" forwarding constructor of my_pair forwards the temporary test object as an rvalue reference which in turn tries to call the explicitly deleted move constructor of test.

如果我们从my_pair并不是那么完美"的构造函数中删除注释,则重载解析会优先使用该注释,并且基本上会强制复制临时test对象,从而使其起作用.

If we remove the comment from my_pair's not so "perfect" constructor it is preferred by overload resolution and basically forces the copy of the temporary test object and thus makes it work.

这篇关于存在完善的转发构造函数时,按左值引用构造函数的意图是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆