move/test/copy_move_optimization.cpp

108 lines
2.5 KiB
C++

//We need to declare:
//
//2 conversions: rv<T> & and const rv<T> &
//1 rv<T> & constructor: move constructor
//1 const rv<T> & constructor: copy constructor
//1 T & constructor: copy constructor
//
//Optimization:
//Since RVO is better than move-construction,
//avoid copy constructor overloading.
#include <boost/move/detail/config_begin.hpp>
#include <boost/move/utility_core.hpp>
#include <iostream>
bool moved = false;
class obj
{
BOOST_COPYABLE_AND_MOVABLE(obj)
public:
obj()
{
std::cout << "constructing obj" << "\n";
}
~obj()
{}
obj(const obj &)
{
std::cout << "copy construct from const obj" << "\n";
}
// copy construct from movable object (non-const rvalue, explicitly moved lvalue)
obj(BOOST_RV_REF(obj))
{
std::cout << "move construct from movable rvalue" << "\n";
}
obj& operator =(BOOST_COPY_ASSIGN_REF(obj))
{
std::cout << "copy assign from const obj" << "\n";
return *this;
}
obj& operator =(BOOST_RV_REF(obj))
{
std::cout << "move assign from movable rvalue" << "\n";
return *this;
}
};
obj rvalue_func() { return obj(); }
const obj const_rvalue_func() { return obj(); }
obj& lvalue_func() { static obj o; return o; }
const obj& const_lvalue_func() { static obj o; return o; }
obj produce() { return obj(); }
void consume(obj){}
int main()
{
{ consume(produce()); }
{ obj o = produce(); }
{ obj o(produce()); }
{
obj o1(rvalue_func());
obj o2 = const_rvalue_func();
obj o3 = lvalue_func();
obj o4 = const_lvalue_func();
// can't explicitly move temporaries
//obj o5 = boost::move(rvalue_func());
obj o5;
//Maybe missed optimization: copied
o5 = rvalue_func();
//Explicit forward works OK and optimized
o5 = boost::forward<obj>(rvalue_func());
obj o7 = boost::move(lvalue_func());
obj o8 = boost::move(const_lvalue_func());
obj o;
o = rvalue_func();
o = const_rvalue_func();
o = lvalue_func();
o = const_lvalue_func();
// can't explicitly move temporaries
//o = boost::move(rvalue_func());
o = boost::forward<obj>(rvalue_func());
o = boost::move(const_rvalue_func());
o = boost::move(lvalue_func());
o = boost::move(const_lvalue_func());
}
return 0;
}
//We need to declare:
//
//2 conversions: rv<T> & and const rv<T> &
//1 rv<T> & constructor: move constructor
//1 const rv<T> & constructor: copy constructor
//1 T & constructor: copy constructor
#include <boost/move/detail/config_end.hpp>