diff --git a/include/boost/fusion/adapted/struct/detail/define_struct.hpp b/include/boost/fusion/adapted/struct/detail/define_struct.hpp index e71dc669..1b968e38 100644 --- a/include/boost/fusion/adapted/struct/detail/define_struct.hpp +++ b/include/boost/fusion/adapted/struct/detail/define_struct.hpp @@ -39,6 +39,8 @@ #define BOOST_FUSION_DEFINE_STRUCT_FILLER_0_END #define BOOST_FUSION_DEFINE_STRUCT_FILLER_1_END +#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + #define BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I( \ R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \ \ @@ -46,6 +48,36 @@ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)( \ other_self.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)) +#define BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR( \ + NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + \ + BOOST_FUSION_GPU_ENABLED \ + NAME(self_type const& other_self) \ + : BOOST_PP_SEQ_FOR_EACH_I_R( \ + 1, \ + BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I, \ + ATTRIBUTE_TUPLE_SIZE, \ + ATTRIBUTES_SEQ) \ + {} + +// Use templated version instead. +#define BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_OP( \ + ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) + +#else // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + +#define BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR( \ + NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + \ + BOOST_FUSION_GPU_ENABLED NAME(self_type const&) = default; + +#define BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_OP( \ + ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + \ + BOOST_FUSION_GPU_ENABLED self_type& operator=(self_type const&) = default; + +#endif // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + #define BOOST_FUSION_DEFINE_STRUCT_ASSIGN_FILLER_I( \ R, ATTRIBUTE_TUPLE_SIZE, I_, ATTRIBUTE) \ \ @@ -85,6 +117,87 @@ return *this; \ } +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR(NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP(ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) + +#else // BOOST_NO_CXX11_RVALUE_REFERENCES + +#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR_FILLER_I( \ + R, ATTRIBUTE_TUPLE_SIZE, I, ATTRIBUTE) \ + \ + BOOST_PP_COMMA_IF(I) \ + BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)(std::move( \ + other_self.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE))) + +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR( \ + NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + \ + BOOST_FUSION_GPU_ENABLED \ + NAME(self_type&& other_self) \ + : BOOST_PP_SEQ_FOR_EACH_I_R( \ + 1, \ + BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR_FILLER_I, \ + ATTRIBUTE_TUPLE_SIZE, \ + ATTRIBUTES_SEQ) \ + {} + +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_FILLER_I( \ + R, ATTRIBUTE_TUPLE_SIZE, I_, ATTRIBUTE) \ + \ + BOOST_PP_EXPR_IF( \ + I_, \ + typedef typename \ + boost::fusion::result_of::next< \ + BOOST_PP_CAT(I,BOOST_PP_DEC(I_)) \ + >::type \ + BOOST_PP_CAT(I,I_); \ + BOOST_PP_CAT(I,I_) BOOST_PP_CAT(i,I_)= \ + boost::fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(I_))); \ + ) \ + \ + BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,1,ATTRIBUTE)=std::move( \ + boost::fusion::deref(BOOST_PP_CAT(i,I_))); + +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP( \ + ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + \ + BOOST_FUSION_GPU_ENABLED \ + self_type& operator=(self_type&& seq) \ + { \ + typedef \ + boost::fusion::result_of::begin::type \ + I0; \ + I0 i0=boost::fusion::begin(seq); \ + \ + BOOST_PP_SEQ_FOR_EACH_I_R( \ + 1, \ + BOOST_FUSION_DEFINE_STRUCT_ASSIGN_FILLER_I, \ + ATTRIBUTE_TUPLE_SIZE, \ + ATTRIBUTES_SEQ) \ + \ + return *this; \ + } + +#else // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR( \ + NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + \ + BOOST_FUSION_GPU_ENABLED NAME(self_type&&) = default; + +#define BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP( \ + ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + \ + BOOST_FUSION_GPU_ENABLED self_type& operator=(self_type&&) = default; + +#endif // BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + +#endif // BOOST_NO_CXX11_RVALUE_REFERENCES + #define BOOST_FUSION_DEFINE_STRUCT_ATTR_I(R, ATTRIBUTE_TUPLE_SIZE, ATTRIBUTE) \ \ BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE,0,ATTRIBUTE) \ @@ -135,14 +248,10 @@ ATTRIBUTES_SEQ) \ {} \ \ - BOOST_FUSION_GPU_ENABLED \ - NAME(self_type const& other_self) \ - : BOOST_PP_SEQ_FOR_EACH_I_R( \ - 1, \ - BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR_FILLER_I, \ - ATTRIBUTE_TUPLE_SIZE, \ - ATTRIBUTES_SEQ) \ - {} \ + BOOST_FUSION_DEFINE_STRUCT_COPY_CTOR( \ + NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + BOOST_FUSION_DEFINE_STRUCT_MOVE_CTOR( \ + NAME, ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ \ template \ BOOST_FUSION_GPU_ENABLED \ @@ -160,6 +269,10 @@ ATTRIBUTES_SEQ) \ {} \ \ + BOOST_FUSION_DEFINE_STRUCT_COPY_ASSIGN_OP( \ + ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ + BOOST_FUSION_DEFINE_STRUCT_MOVE_ASSIGN_OP( \ + ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) \ BOOST_FUSION_DEFINE_STRUCT_ASSIGN_OP(ATTRIBUTES_SEQ, ATTRIBUTE_TUPLE_SIZE) #define BOOST_FUSION_DEFINE_STRUCT_CTOR_1( \ diff --git a/test/Jamfile b/test/Jamfile index b2047ccc..072126ae 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -207,16 +207,22 @@ project [ run sequence/adt_attribute_proxy.cpp : : : : ] [ run sequence/define_struct.cpp : : : : ] [ run sequence/define_struct_empty.cpp : : : : ] + [ run sequence/define_struct_move.cpp : : : : ] [ run sequence/define_struct_inline.cpp : : : : ] [ run sequence/define_struct_inline_empty.cpp : : : : ] + [ run sequence/define_struct_inline_move.cpp : : : : ] [ run sequence/define_assoc_struct.cpp : : : : ] [ run sequence/define_assoc_struct_empty.cpp : : : : ] + [ run sequence/define_assoc_struct_move.cpp : : : : ] [ run sequence/define_tpl_struct.cpp : : : : ] [ run sequence/define_tpl_struct_empty.cpp : : : : ] + [ run sequence/define_tpl_struct_move.cpp : : : : ] [ run sequence/define_tpl_struct_inline.cpp : : : : ] [ run sequence/define_tpl_struct_inline_empty.cpp : : : : ] + [ run sequence/define_tpl_struct_inline_move.cpp : : : : ] [ run sequence/define_assoc_tpl_struct.cpp : : : : ] [ run sequence/define_assoc_tpl_struct_empty.cpp : : : : ] + [ run sequence/define_assoc_tpl_struct_move.cpp : : : : ] [ run sequence/std_tuple.cpp : : : : ] [ run sequence/std_tuple_iterator.cpp : : : : ] [ run sequence/ref_vector.cpp : : : : ] diff --git a/test/sequence/define_assoc_struct_move.cpp b/test/sequence/define_assoc_struct_move.cpp new file mode 100644 index 00000000..97c3d7ee --- /dev/null +++ b/test/sequence/define_assoc_struct_move.cpp @@ -0,0 +1,78 @@ +/*============================================================================= + Copyright (c) 2016 Kohei Takahashi + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include +#include +#include + +struct key_type; +struct wrapper +{ + int value; + + wrapper() : value(42) {} + wrapper(wrapper&& other) : value(other.value) { other.value = 0; } + wrapper(wrapper const& other) : value(other.value) {} + + wrapper& operator=(wrapper&& other) { value = other.value; other.value = 0; return *this; } + wrapper& operator=(wrapper const& other) { value = other.value; return *this; } +}; +BOOST_FUSION_DEFINE_ASSOC_STRUCT((ns), value, (wrapper, w, key_type)) + +int main() +{ + using namespace boost::fusion; + + { + ns::value x; + ns::value y(x); // copy + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 43); + + y = x; // copy assign + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + } + + { + ns::value x; + ns::value y(std::move(x)); // move + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 43); + + y = std::move(x); // move assign + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 0); + } + + return boost::report_errors(); +} + +#else + +int main() +{ +} + +#endif diff --git a/test/sequence/define_assoc_tpl_struct_move.cpp b/test/sequence/define_assoc_tpl_struct_move.cpp new file mode 100644 index 00000000..dcffa566 --- /dev/null +++ b/test/sequence/define_assoc_tpl_struct_move.cpp @@ -0,0 +1,78 @@ +/*============================================================================= + Copyright (c) 2016 Kohei Takahashi + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include +#include +#include + +struct key_type; +struct wrapper +{ + int value; + + wrapper() : value(42) {} + wrapper(wrapper&& other) : value(other.value) { other.value = 0; } + wrapper(wrapper const& other) : value(other.value) {} + + wrapper& operator=(wrapper&& other) { value = other.value; other.value = 0; return *this; } + wrapper& operator=(wrapper const& other) { value = other.value; return *this; } +}; +BOOST_FUSION_DEFINE_ASSOC_TPL_STRUCT((W), (ns), value, (W, w, key_type)) + +int main() +{ + using namespace boost::fusion; + + { + ns::value x; + ns::value y(x); // copy + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 43); + + y = x; // copy assign + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + } + + { + ns::value x; + ns::value y(std::move(x)); // move + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 43); + + y = std::move(x); // move assign + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 0); + } + + return boost::report_errors(); +} + +#else + +int main() +{ +} + +#endif diff --git a/test/sequence/define_struct_inline_move.cpp b/test/sequence/define_struct_inline_move.cpp new file mode 100644 index 00000000..13d37931 --- /dev/null +++ b/test/sequence/define_struct_inline_move.cpp @@ -0,0 +1,81 @@ +/*============================================================================= + Copyright (c) 2016 Kohei Takahashi + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include +#include +#include + +struct wrapper +{ + int value; + + wrapper() : value(42) {} + wrapper(wrapper&& other) : value(other.value) { other.value = 0; } + wrapper(wrapper const& other) : value(other.value) {} + + wrapper& operator=(wrapper&& other) { value = other.value; other.value = 0; return *this; } + wrapper& operator=(wrapper const& other) { value = other.value; return *this; } +}; + +namespace ns +{ + BOOST_FUSION_DEFINE_STRUCT_INLINE(value, (wrapper, w)) +} + +int main() +{ + using namespace boost::fusion; + + { + ns::value x; + ns::value y(x); // copy + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 43); + + y = x; // copy assign + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + } + + { + ns::value x; + ns::value y(std::move(x)); // move + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 43); + + y = std::move(x); // move assign + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 0); + } + + return boost::report_errors(); +} + +#else + +int main() +{ +} + +#endif diff --git a/test/sequence/define_struct_move.cpp b/test/sequence/define_struct_move.cpp new file mode 100644 index 00000000..9f9036bb --- /dev/null +++ b/test/sequence/define_struct_move.cpp @@ -0,0 +1,77 @@ +/*============================================================================= + Copyright (c) 2016 Kohei Takahashi + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include +#include +#include + +struct wrapper +{ + int value; + + wrapper() : value(42) {} + wrapper(wrapper&& other) : value(other.value) { other.value = 0; } + wrapper(wrapper const& other) : value(other.value) {} + + wrapper& operator=(wrapper&& other) { value = other.value; other.value = 0; return *this; } + wrapper& operator=(wrapper const& other) { value = other.value; return *this; } +}; +BOOST_FUSION_DEFINE_STRUCT((ns), value, (wrapper, w)) + +int main() +{ + using namespace boost::fusion; + + { + ns::value x; + ns::value y(x); // copy + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 43); + + y = x; // copy assign + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + } + + { + ns::value x; + ns::value y(std::move(x)); // move + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 43); + + y = std::move(x); // move assign + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 0); + } + + return boost::report_errors(); +} + +#else + +int main() +{ +} + +#endif diff --git a/test/sequence/define_tpl_struct_inline_move.cpp b/test/sequence/define_tpl_struct_inline_move.cpp new file mode 100644 index 00000000..9917fea2 --- /dev/null +++ b/test/sequence/define_tpl_struct_inline_move.cpp @@ -0,0 +1,81 @@ +/*============================================================================= + Copyright (c) 2016 Kohei Takahashi + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include +#include +#include + +struct wrapper +{ + int value; + + wrapper() : value(42) {} + wrapper(wrapper&& other) : value(other.value) { other.value = 0; } + wrapper(wrapper const& other) : value(other.value) {} + + wrapper& operator=(wrapper&& other) { value = other.value; other.value = 0; return *this; } + wrapper& operator=(wrapper const& other) { value = other.value; return *this; } +}; + +namespace ns +{ + BOOST_FUSION_DEFINE_TPL_STRUCT_INLINE((W), value, (W, w)) +} + +int main() +{ + using namespace boost::fusion; + + { + ns::value x; + ns::value y(x); // copy + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 43); + + y = x; // copy assign + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + } + + { + ns::value x; + ns::value y(std::move(x)); // move + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 43); + + y = std::move(x); // move assign + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 0); + } + + return boost::report_errors(); +} + +#else + +int main() +{ +} + +#endif diff --git a/test/sequence/define_tpl_struct_move.cpp b/test/sequence/define_tpl_struct_move.cpp new file mode 100644 index 00000000..127e5ce0 --- /dev/null +++ b/test/sequence/define_tpl_struct_move.cpp @@ -0,0 +1,77 @@ +/*============================================================================= + Copyright (c) 2016 Kohei Takahashi + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include +#include +#include + +struct wrapper +{ + int value; + + wrapper() : value(42) {} + wrapper(wrapper&& other) : value(other.value) { other.value = 0; } + wrapper(wrapper const& other) : value(other.value) {} + + wrapper& operator=(wrapper&& other) { value = other.value; other.value = 0; return *this; } + wrapper& operator=(wrapper const& other) { value = other.value; return *this; } +}; +BOOST_FUSION_DEFINE_TPL_STRUCT((W), (ns), value, (W, w)) + +int main() +{ + using namespace boost::fusion; + + { + ns::value x; + ns::value y(x); // copy + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 43); + + y = x; // copy assign + + BOOST_TEST(x.w.value == 42); + BOOST_TEST(y.w.value == 42); + } + + { + ns::value x; + ns::value y(std::move(x)); // move + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 42); + + ++y.w.value; + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 43); + + y = std::move(x); // move assign + + BOOST_TEST(x.w.value == 0); + BOOST_TEST(y.w.value == 0); + } + + return boost::report_errors(); +} + +#else + +int main() +{ +} + +#endif