(as for now, I'm working on a stupid macro...)
Yeah, I went that route too. Here's your macro:
// detail/move_default.hpp #ifndef UTILITY_DETAIL_MOVE_DEFAULT_HPP #define UTILITY_DETAIL_MOVE_DEFAULT_HPP #include <boost/preprocessor.hpp> #define UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR_BASE(pR, pData, pBase) pBase(std::move(pOther)) #define UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT_BASE(pR, pData, pBase) pBase::operator=(std::move(pOther)); #define UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR(pR, pData, pMember) pMember(std::move(pOther.pMember)) #define UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT(pR, pData, pMember) pMember = std::move(pOther.pMember); #define UTILITY_MOVE_DEFAULT_DETAIL(pT, pBases, pMembers) \ pT(pT&& pOther) : \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR_BASE, BOOST_PP_EMPTY, pBases)) \ , \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR, BOOST_PP_EMPTY, pMembers)) \ {} \ \ pT& operator=(pT&& pOther) \ { \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT_BASE, BOOST_PP_EMPTY, pBases) \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT, BOOST_PP_EMPTY, pMembers) \ \ return *this; \ } #define UTILITY_MOVE_DEFAULT_BASES_DETAIL(pT, pBases) \ pT(pT&& pOther) : \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR_BASE, BOOST_PP_EMPTY, pBases)) \ {} \ \ pT& operator=(pT&& pOther) \ { \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT_BASE, BOOST_PP_EMPTY, pBases) \ \ return *this; \ } #define UTILITY_MOVE_DEFAULT_MEMBERS_DETAIL(pT, pMembers) \ pT(pT&& pOther) : \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \ UTILITY_MOVE_DEFAULT_DETAIL_CONSTRUCTOR, BOOST_PP_EMPTY, pMembers)) \ {} \ \ pT& operator=(pT&& pOther) \ { \ BOOST_PP_SEQ_FOR_EACH(UTILITY_MOVE_DEFAULT_DETAIL_ASSIGNMENT, BOOST_PP_EMPTY, pMembers) \ \ return *this; \ } #endif
// move_default.hpp #ifndef UTILITY_MOVE_DEFAULT_HPP #define UTILITY_MOVE_DEFAULT_HPP #include "utility/detail/move_default.hpp" // move bases and members #define UTILITY_MOVE_DEFAULT(pT, pBases, pMembers) UTILITY_MOVE_DEFAULT_DETAIL(pT, pBases, pMembers) // base only version #define UTILITY_MOVE_DEFAULT_BASES(pT, pBases) UTILITY_MOVE_DEFAULT_BASES_DETAIL(pT, pBases) // member only version #define UTILITY_MOVE_DEFAULT_MEMBERS(pT, pMembers) UTILITY_MOVE_DEFAULT_MEMBERS_DETAIL(pT, pMembers) #endif
(I've removed the real comments, which are length and documentary.)
You specify the bases and/or members in your class as a preprocessor list, for example:
#include "move_default.hpp" struct foo { UTILITY_MOVE_DEFAULT_MEMBERS(foo, (x)(str)); int x; std::string str; }; struct bar : foo, baz { UTILITY_MOVE_DEFAULT_BASES(bar, (foo)(baz)); }; struct baz : bar { UTILITY_MOVE_DEFAULT(baz, (bar), (ptr)); void* ptr; };
And out comes a move-constructor and move-assignment operator.
(As an aside, if anyone knows how I could combine the details into one macro, that would be swell.)
MyClass::MyClass(Myclass &&) = default;?