使用boost :: move将数据移动到std :: make_pair

时间:2014-08-13 02:13:12

标签: c++ c++11 boost

  • boost_1_55
  • 编译器:vc2008
  • os:win7 32位

这一项工作

std::pair<std::vector<std::string>, int> move_pair()
{
    std::vector<std::string> temp;
    //do some jobs
    return std::make_pair(std::move(temp), 0);
}

但是这个不行(不能用boost :: move来移动temp)

std::pair<boost::container::vector<std::string>, int> move_pair()
{
    boost::container::vector<std::string> temp;
    //do some jobs

    return std::make_pair(boost::move(temp), 0);
}

无论如何用std :: pair的c ++ 98/03编译器来移动boost :: container的temp? 是否存在boost :: container :: pair,boost :: container :: make_pair?

错误消息

..\networkLibTest\main.cpp(18) : error C2248: 'boost::rv<T>::rv' : cannot access private member declared in class 'boost::rv<T>'
        with
        [
            T=boost::container::vector<std::string>
        ]
        g:\Tools\3rdLibs\boost\boost_1_55_0\boost/move/core.hpp(71) : see declaration of 'boost::rv<T>::rv'
        with
        [
            T=boost::container::vector<std::string>
        ]
..\networkLibTest\main.cpp(18) : error C2248: 'boost::rv<T>::~rv' : cannot access private member declared in class 'boost::rv<T>'
        with
        [
            T=boost::container::vector<std::string>
        ]
        g:\Tools\3rdLibs\boost\boost_1_55_0\boost/move/core.hpp(70) : see declaration of 'boost::rv<T>::~rv'
        with
        [
            T=boost::container::vector<std::string>
        ]

2 个答案:

答案 0 :(得分:3)

boost::move通过将提供的引用的类型基本上转换为不同的“包裹”类型来模拟C ++ 98模式中的移动语义,该类型表示“嘿,我是一个右手,从我这里抢走!”。

但是,为了实现这一点,类型的构造函数/赋值运算符必须能够识别这种“包装”类型并相应地执行,这意味着这需要来自类型的协作。

std::vector显然对提升一无所知,非合作类型的boost::move实现只返回传递给它的内容,所以你的代码用std::vector编译,但实际上是复制的而不是移动。

虽然boost::container::vector是一种协作类型,但移动语义模拟使用的包装类型不可构造,可复制,甚至可以破坏 - boost::move返回的引用是通过{{1}获得的传入的引用。因此,你不能使用返回值为static_cast的C ++ 03 make_pair,因为C ++ 03 boost::move按值获取其参数,会尝试制作包装类型的副本,并努力工作。如果您使用make_pair,您可以做的最好是直接调用boost::move的构造函数:

std::pair

return std::pair<boost::container::vector<std::string>, int>(boost::move(temp), 0); 移动到临时temp并将该临时文件传递给boost::container::vector<std::string>的构造函数,但由于std::pair的构造函数通过std::pair获取其参数引用而不是按值,因此无论如何都会制作副本,这样做是没有意义的。

答案 1 :(得分:0)

我只是提出一个天真的对和make_pair,不知道这个实现是否隐藏了任何陷阱

pair.hpp

namespace wlg{

template<typename T1, typename T2>
class pair
{
public:
    typedef T1 first_type;
    typedef T2 second_type;

    pair(T1 const &fir, T2 const &sec);
    pair(BOOST_RV_REF(T1) fir, T2 const &sec);
    pair(T1 const &first, BOOST_RV_REF(T2) sec);
    pair(BOOST_RV_REF(T1) fir, BOOST_RV_REF(T2) sec) :
        first(boost::move(fir)),
        second(boost::move(sec))
    {
#ifdef WLG_PAIR_DEBUG_ENABLE
        std::cout<<"pair(BOOST_RV_REF(T1) first, BOOST_RV_REF(T2) second)"<<std::endl;
#endif
    }

    pair(pair const &data);
    pair(BOOST_RV_REF(pair) data)            //Move constructor
        : first(boost::move(data.first)),
          second(boost::move(data.second))
    {
#ifdef WLG_PAIR_DEBUG_ENABLE
        std::cout<<"pair(BOOST_RV_REF(pair) data)"<<std::endl;
#endif
    }

    pair& operator=(BOOST_COPY_ASSIGN_REF(pair) data);

    pair& operator=(BOOST_RV_REF(pair) data) //Move assignment
    {
#ifdef WLG_PAIR_DEBUG_ENABLE
        std::cout<<"operator=(BOOST_RV_REF(pair) data)"<<std::endl;
#endif
        if (this != &data){
            first = boost::move(data.first);
            second = boost::move(data.second);
        }
        return *this;
    }

    void swap(pair &data)
    {
        swap(data.first, first);
        swap(data.second, second);
    }

private:
    template<class T>
    void swap(T &fir, T &sec)
    {
        T tmp(::boost::move(fir));
        fir = ::boost::move(sec);
        sec = ::boost::move(tmp);
    }

public:
    T1 first;
    T2 second;

private:
    BOOST_COPYABLE_AND_MOVABLE(pair)
};

template<typename T1, typename T2>
pair<T1, T2>::pair(const T1 &fir, const T2 &sec) :
    first(fir),
    second(sec)
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"pair(const T1 &first, const T2 &second)"<<std::endl;
#endif
}

template<typename T1, typename T2>
pair<T1, T2>::pair(BOOST_RV_REF(T1) fir, const T2 &sec) :
    first(boost::move(fir)),
    second(sec)
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"pair(BOOST_RV_REF(T1) first, const T2 &second)"<<std::endl;
#endif
}

template<typename T1, typename T2>
pair<T1, T2>::pair(const T1 &fir, BOOST_RV_REF(T2) sec) :
    first(fir),
    second(boost::move(sec))
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"pair(const T1 &first, BOOST_RV_REF(T2) second)"<<std::endl;
#endif
}

template<typename T1, typename T2>
pair<T1, T2>::pair(const pair &data) :
    first(data.first),
    second(data.second)
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"pair(const pair &data)"<<std::endl;
#endif
}

template<typename T1, typename T2>
inline
pair<T1, T2> make_pair(T1 const &fir, T2 const &sec)
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"make_pair(T1 const &first, T2 const &second)"<<std::endl;
#endif
    return pair<T1, T2>(fir, sec);
}

template<typename T1, typename T2>
inline
pair<T1, T2> make_pair(BOOST_RV_REF(T1) fir, T2 const &sec)
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"make_pair(BOOST_RV_REF(T1) first, T2 const &second)"<<std::endl;
#endif
    return pair<T1, T2>(boost::move(fir), sec);
}

template<typename T1, typename T2>
inline
pair<T1, T2> make_pair(T1 const &fir, BOOST_RV_REF(T2) sec)
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"make_pair(T1 const &first, BOOST_RV_REF(T2) second)"<<std::endl;
#endif
    return pair<T1, T2>(fir, boost::move(sec));
}

template<typename T1, typename T2>
inline
pair<T1, T2> make_pair(BOOST_RV_REF(T1) fir, BOOST_RV_REF(T2) sec)
{
#ifdef WLG_PAIR_DEBUG_ENABLE
    std::cout<<"make_pair(BOOST_RV_REF(T1) first, BOOST_RV_REF(T2) second)"<<std::endl;
#endif
    return pair<T1, T2>(boost::move(fir), boost::move(sec));
}

template<typename T1, typename T2>
inline
bool operator==(pair<T1, T2> const &fir, pair<T1, T2> const &sec)
{
    return fir.first == sec.first && fir.second == sec.second;
}

template<typename T1, typename T2>
inline
bool operator!=(pair<T1, T2> const &fir, pair<T1, T2> const &sec)
{
    return !(fir == sec);
}

template<typename T1, typename T2>
inline
bool operator>=(pair<T1, T2> const &fir, pair<T1, T2> const &sec)
{
    return fir.first >= sec.first && fir.second >= sec.second;
}

template<typename T1, typename T2>
inline
bool operator<=(pair<T1, T2> const &fir, pair<T1, T2> const &sec)
{
    return !(fir >= sec);
}

template<typename T1, typename T2>
inline
bool operator>(pair<T1, T2> const &fir, pair<T1, T2> const &sec)
{
    return fir.first > sec.first && fir.second > sec.second;
}

template<typename T1, typename T2>
inline
bool operator<(pair<T1, T2> const &fir, pair<T1, T2> const &sec)
{
    return !(fir > sec);
}

}

测试代码

#define WLG_PAIR_DEBUG_ENABLE

#include "pair.h"

#include <boost/container/vector.hpp>
#include <boost/move/move.hpp>

#include <string>

Type make_pair_00()
{
    boost::container::vector<std::string> temp_1;
    boost::container::vector<std::string> temp_2;

    return wlg::make_pair(temp_1, temp_2);
}

Type make_pair_01()
{
    boost::container::vector<std::string> temp_1;
    boost::container::vector<std::string> temp_2;

    return wlg::make_pair(boost::move(temp_1), temp_2);
}

Type make_pair_02()
{
    boost::container::vector<std::string> temp_1;
    boost::container::vector<std::string> temp_2;

    return wlg::make_pair(temp_1, boost::move(temp_2));
}

Type make_pair_03()
{
    boost::container::vector<std::string> temp_1;
    boost::container::vector<std::string> temp_2;

    return wlg::make_pair(boost::move(temp_1), boost::move(temp_2));
}

int main()
{        
    Type target_00 = make_pair_00();
    std::cout<<std::endl;

    Type target_01 = make_pair_01();
    std::cout<<std::endl;

    Type target_02 = make_pair_02();
    std::cout<<std::endl;

    Type target_03 = make_pair_03();
    std::cout<<std::endl;

    Type target_04 = boost::move(target_00);
    std::cout<<std::endl;

    target_00 = make_pair_00();
    std::cout<<std::endl;
}

结果

make_pair(T1 const &first, T2 const &second)
pair(const T1 &first, const T2 &second)

make_pair(BOOST_RV_REF(T1) first, T2 const &second)
pair(BOOST_RV_REF(T1) first, const T2 &second)

make_pair(T1 const &first, BOOST_RV_REF(T2) second)
pair(const T1 &first, BOOST_RV_REF(T2) second)

make_pair(BOOST_RV_REF(T1) first, BOOST_RV_REF(T2) second)
pair(BOOST_RV_REF(T1) first, BOOST_RV_REF(T2) second)

pair(BOOST_RV_REF(pair) data)

make_pair(T1 const &first, T2 const &second)
pair(const T1 &first, const T2 &second)
operator=(BOOST_RV_REF(pair) data)

target_00~target_03不调用任何拷贝构造函数,也许它是由RVO优化的?