代码之家  ›  专栏  ›  技术社区  ›  Jonathan Mee

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

  •  3
  • Jonathan Mee  · 技术社区  · 9 年前

    我试图模仿 tie C++11之前的版本。

    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;
    }
    

    This works 但是如果我使用 make_pair 而不是到 pair 建造师 a b 未分配。
    为什么 一对 构造函数工作但不工作 制造_空气 ?

    3 回复  |  直到 9 年前
        1
  •  3
  •   W.F.    9 年前

    实际上你可以用 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;
    }
    
        2
  •  3
  •   Jonathan Mee    9 年前

    pair 使用“显式类型”,而 make_pair

    这就是为什么标准定义了 一对 :

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

    如果在 C++03 compiler

    非静态引用成员 int& std::pair<int&, int&>::first ,无法使用默认赋值运算符

    问题是 一对 使用 implicitly-declared copy assignment operator 如果 一对 :

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

    是否由定义 制造_空气 一对 构造函数,模板参数将定义 一对 的成员为 int& 因此,不会定义隐式声明的复制赋值运算符。 因此,这不能用 一对 在C++03中。

    如果不希望使用返回参数,可以编写自己的 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;
        }
    };
    

    一对 :

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

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

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

    这将允许分配 一对 就像在C++11:

    tie(a, b) = test();
    

    Live Example

    请注意,这仍然不能容忍使用 模板参数,所以 details::tie<int&, int&> tie<int&, int&> 将一如既往地失败。

        3
  •  2
  •   krzaq    9 年前

    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

    这是C++03没有ref限定符的一个不幸的副作用。在C++11中,您可以删除 operator= 对于rvalue this (在非std类中),并使此类情况成为编译器错误,而不是无声的意外行为。