Reputation: 521
I am using:
This works for me:
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);
}
But this one does not work (can not use boost::move
to 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);
}
Is there any way to move the temp
of boost::container
with std::pair
from a c++98/03 compiler?
Is there a boost::container::pair
or boost::container::make_pair
I should use?
Error message:
..\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>
]
Upvotes: 1
Views: 1233
Reputation: 521
I just come up a naive pair and make_pair, do not know there are any pitfall hidden by this implementation or not
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);
}
}
Test codes
#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;
}
The results
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 do not call any copy constructor, maybe it is optimize by RVO?
Upvotes: 0
Reputation: 137425
boost::move
emulates move semantics in C++98 mode by essentially casting the type of the provided reference into a different "wrapped" type that says "hey, I'm an rvalue, steal from me!".
However, for this to work, the type's constructors/assignment operators must be able to recognize this "wrapped" type and act accordingly, which means that this requires cooperation from the type.
std::vector
obviously knows nothing about boost, and the boost::move
implementation for non-cooperating types simply returns what is passed to it, so your code with std::vector
compiles, but actually copies rather than moves.
Although boost::container::vector
is a cooperating type, the wrapped type used by the move semantics emulation is not constructible, copyable, or even destructible - the reference returned by boost::move
is obtained via a static_cast
on the reference passed in. Thus, you can't use C++03 make_pair
with the return value of boost::move
because C++03 make_pair
takes its parameters by value, which would attempt to make a copy of the wrapped type, and fail hard. If you use boost::move
, the best you can do is calling std::pair
's constructor directly:
return std::pair<boost::container::vector<std::string>, int>(boost::move(temp), 0);
which moves temp
into a temporary boost::container::vector<std::string>
and pass that temporary to std::pair
's constructor, but since std::pair
's constructor takes its arguments by const
reference and not by value, and hence will make a copy anyway, there is no point in doing this.
Upvotes: 3