为什么我不能用make_pair打领带?

Why can't I use make_pair to tie?

本文关键字:pair 不能 make 为什么      更新时间:2023-10-16

我正在尝试模仿C++11之前的tie的行为。

pair<int, int> test() {
    return make_pair(13, 42);
}
int main() {
    int a = 1, b = 2;
    pair<int&, int&>(a, b) = test();
    cout << a << ' ' << b << endl;
}

但是,如果我使用make_pair来代替pair构造函数ab,则这是有效的
为什么pair构造函数可以工作而make_pair不能工作?

实际上您可以使用std::make_pair。但是您需要实现reference_wrapper类来模仿引用。示例(不是很完善,但如预期那样工作(c++03方法:

#include <iostream>
#include <utility>
using namespace std;
template <class T>
struct reference_wrapper {
   bool is_const;
   T* v;
   T const* cv;
   reference_wrapper(T& t): v(&t), is_const(false) { }
   reference_wrapper(T const& t): cv(&t), is_const(true) { }
   reference_wrapper &operator=(reference_wrapper const &rw) {
      if (rw.is_const) {
         *v = *rw.cv;
      } else {
         *v = *rw.v;
      }
   }
};
template <class T>
reference_wrapper<T> ref(T &t) {
   return reference_wrapper<T>(t);
}
pair<int, int> test() {
    return make_pair(13, 42);
}
int main() {
    int a = 1, b = 2;
    //pair<int&, int&>(a, b) = test();  // works
    make_pair(ref(a), ref(b)) = test(); // now it does work
    std::cout << a << ' ' << b << std::endl;
}

在20.2.2[lib.pears]8中,标准规定pair使用"显式类型",而make_pair的"类型是推导出来的"。

这就是为什么标准定义了pair:的构造函数

template <class T1, class T2>
pair(const T1& x, const T2& y)

如果你在C++03编译器上运行你的代码,你会得到这个错误:

非静态引用成员int& std::pair<int&, int&>::first,不能使用默认分配运算符

问题是pair使用隐式声明的拷贝分配运算符,如果pair:

具有引用类型的非静态数据成员

无论是由make_pair还是pair构造函数定义,模板参数都会将pair的两个成员定义为int&,因此不会定义隐式声明的复制赋值运算符所以这不能用C++03中的pair来完成。

如果不希望使用return参数,您可以编写自己的tie:实现

template <class T1, class T2>
struct tie{
    T1& first;
    T2& second;
    tie(T1& x, T2& y) : first(x), second(y) {}
    tie<T1, T2>& operator=(const pair<T1, T2>& rhs){
        first = rhs.first;
        second = rhs.second;
        return *this;
    }
};

这将允许分配pair:

tie<int, int>(a, b) = test();

要获得不需要模板参数的C++11行为,您需要定义一个函数。如果tie嵌套在namespace details中,则函数可以定义为:

template <class T1, class T2>
details::tie<T1, T2> tie(T1& x, T2& y) { 
    return details::tie<T1, T2>(x, y);
}

这将允许分配pair,就像在C++11:中一样

tie(a, b) = test();

实时示例

请注意,这仍然不能容忍使用int&模板参数,因此details::tie<int&, int&>tie<int&, int&>将像以前一样失败

make_pair生成一对值,而不是引用。这意味着它将在您的示例中生成pair<int, int>,并且您将把test()的结果分配给一个临时变量。

您可以使用以下内容模拟tie

template<typename T, typename U>
std::pair<T&, U&> tie_pair(T& l, U& r)
{
    return std::pair<T&, U&>(l, r);
}

http://ideone.com/muAcaG

cco​这是C++03没有ref限定符的不幸副作用。在C++≥11中,您可以删除右值thisoperator=(在非std类中(,并使这种情况成为编译器错误,而不是无声的意外行为。

相关文章: