template<class T, class Tp> T make_from_tuple(Tp&& tp);+
diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 12d2697..3454142 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -592,6 +592,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
N
is std::tuple_size<typename std::remove_reference&
+make_from_tuple<T>(tp)
+
+
+template<class T, class Tp> T make_from_tuple(Tp&& tp);
+
+
+
+make_from_tuple<T>(tp)
returns T(std::get<J>(std::forward<Tp>(tp))…)
for J
in 0..N-1
,
+where N
is std::tuple_size<typename std::remove_reference<Tp>::type>::value
. Same as std::make_from_tuple
in C++17.
+
+
+
tuple_for_each(tp, f)
diff --git a/doc/mp11/tuple.adoc b/doc/mp11/tuple.adoc
index b9dd82c..2dc9f99 100644
--- a/doc/mp11/tuple.adoc
+++ b/doc/mp11/tuple.adoc
@@ -20,6 +20,13 @@ http://www.boost.org/LICENSE_1_0.txt
`tuple_apply(f, tp)` returns `std::forward(f)(std::get(std::forward(tp))...)` for `J` in 0..`N-1`,
where `N` is `std::tuple_size::type>::value`. Same as `std::apply` in C++17.
+## make_from_tuple(tp)
+
+ template T make_from_tuple(Tp&& tp);
+
+`make_from_tuple(tp)` returns `T(std::get(std::forward(tp))...)` for `J` in 0..`N-1`,
+where `N` is `std::tuple_size::type>::value`. Same as `std::make_from_tuple` in C++17.
+
## tuple_for_each(tp, f)
template constexpr F tuple_for_each(Tp&& tp, F&& f);
diff --git a/include/boost/mp11/tuple.hpp b/include/boost/mp11/tuple.hpp
index 754295c..db8ce05 100644
--- a/include/boost/mp11/tuple.hpp
+++ b/include/boost/mp11/tuple.hpp
@@ -41,6 +41,24 @@ BOOST_CONSTEXPR auto tuple_apply( F && f, Tp && tp )
return detail::tuple_apply_impl( std::forward(f), std::forward(tp), Seq() );
}
+// make_from_tuple
+namespace detail
+{
+
+template BOOST_CONSTEXPR T make_from_tuple_impl( Tp && tp, integer_sequence )
+{
+ return T( std::get(std::forward(tp))... );
+}
+
+} // namespace detail
+
+template::type>::value>>
+BOOST_CONSTEXPR T make_from_tuple( Tp && tp )
+{
+ return detail::make_from_tuple_impl( std::forward(tp), Seq() );
+}
+
// tuple_for_each
namespace detail
{
diff --git a/include/boost/mp11_single.hpp b/include/boost/mp11_single.hpp
index c4086e2..b45c39f 100644
--- a/include/boost/mp11_single.hpp
+++ b/include/boost/mp11_single.hpp
@@ -2695,6 +2695,24 @@ BOOST_CONSTEXPR auto tuple_apply( F && f, Tp && tp )
return detail::tuple_apply_impl( std::forward(f), std::forward(tp), Seq() );
}
+// make_from_tuple
+namespace detail
+{
+
+template BOOST_CONSTEXPR T make_from_tuple_impl( Tp && tp, integer_sequence )
+{
+ return T( std::get(std::forward(tp))... );
+}
+
+} // namespace detail
+
+template::type>::value>>
+BOOST_CONSTEXPR T make_from_tuple( Tp && tp )
+{
+ return detail::make_from_tuple_impl( std::forward(tp), Seq() );
+}
+
// tuple_for_each
namespace detail
{
diff --git a/test/Jamfile b/test/Jamfile
index 02cd885..fbad85d 100644
--- a/test/Jamfile
+++ b/test/Jamfile
@@ -98,6 +98,8 @@ run tuple_for_each.cpp : : : $(REQ) ;
run tuple_for_each_cx.cpp : : : $(REQ) ;
run tuple_apply.cpp : : : $(REQ) ;
run tuple_apply_cx.cpp : : : $(REQ) ;
+run make_from_tuple.cpp : : : $(REQ) ;
+run make_from_tuple_cx.cpp : : : $(REQ) ;
# set
run mp_set_contains.cpp : : : $(REQ) ;
diff --git a/test/make_from_tuple.cpp b/test/make_from_tuple.cpp
new file mode 100644
index 0000000..491a4a7
--- /dev/null
+++ b/test/make_from_tuple.cpp
@@ -0,0 +1,219 @@
+
+// Copyright 2015, 2017 Peter Dimov.
+//
+// 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct T1
+{
+ int x, y, z;
+
+ T1( int x = 0, int y = 0, int z = 0 ): x(x), y(y), z(z) {}
+};
+
+struct T2
+{
+ std::unique_ptr x, y, z;
+
+ T2( std::unique_ptr x, std::unique_ptr y, std::unique_ptr z ): x(std::move(x)), y(std::move(y)), z(std::move(z)) {}
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
+
+ T2( T2&& r ): x( std::move(r.x) ), y( std::move(r.y) ), z( std::move(r.z) ) {}
+
+#endif
+};
+
+int main()
+{
+ using boost::mp11::make_from_tuple;
+
+ {
+ std::tuple tp{ 1, 2, 3 };
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+ {
+ std::tuple const tp{ 1, 2, 3 };
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 8
+#else
+
+ {
+ std::tuple, std::unique_ptr, std::unique_ptr> tp{ std::unique_ptr(new int(1)), std::unique_ptr(new int(2)), std::unique_ptr(new int(3)) };
+
+ T2 t2 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( *t2.x, 1 );
+ BOOST_TEST_EQ( *t2.y, 2 );
+ BOOST_TEST_EQ( *t2.z, 3 );
+ }
+
+#endif
+
+ {
+ std::pair tp{ 1, 2 };
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ {
+ std::pair const tp{ 1, 2 };
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ {
+ std::array tp{{ 1, 2, 3 }};
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+ {
+ std::array const tp{{ 1, 2, 3 }};
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 1 );
+ BOOST_TEST_EQ( t1.y, 2 );
+ BOOST_TEST_EQ( t1.z, 3 );
+ }
+ }
+
+ {
+ std::tuple<> tp;
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ {
+ std::array tp;
+
+ {
+ T1 t1 = make_from_tuple( tp );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+
+ {
+ T1 t1 = make_from_tuple( std::move(tp) );
+
+ BOOST_TEST_EQ( t1.x, 0 );
+ BOOST_TEST_EQ( t1.y, 0 );
+ BOOST_TEST_EQ( t1.z, 0 );
+ }
+ }
+
+ return boost::report_errors();
+}
diff --git a/test/make_from_tuple_cx.cpp b/test/make_from_tuple_cx.cpp
new file mode 100644
index 0000000..7f2f1ab
--- /dev/null
+++ b/test/make_from_tuple_cx.cpp
@@ -0,0 +1,76 @@
+
+// Copyright 2015 Peter Dimov.
+//
+// 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
+#include
+
+// Technically std::tuple isn't constexpr enabled in C++11, but it works with libstdc++
+
+#if defined( BOOST_NO_CXX11_CONSTEXPR ) || ( defined( _LIBCPP_VERSION ) && __cplusplus < 201400L )
+
+int main() {}
+
+#else
+
+#include
+#include
+#include
+
+struct T1
+{
+ int x, y, z;
+
+ constexpr T1( int x = 0, int y = 0, int z = 0 ): x(x), y(y), z(z) {}
+};
+
+int main()
+{
+ using boost::mp11::make_from_tuple;
+
+ {
+ constexpr std::tuple tp{ 1, 2, 3 };
+
+ constexpr auto r = make_from_tuple( tp );
+
+ static_assert( r.x == 1, "r.x == 1" );
+ static_assert( r.y == 2, "r.y == 2" );
+ static_assert( r.z == 3, "r.z == 3" );
+ }
+
+ {
+ constexpr std::pair tp{ 1, 2 };
+
+ constexpr auto r = make_from_tuple( tp );
+
+ static_assert( r.x == 1, "r.x == 1" );
+ static_assert( r.y == 2, "r.y == 2" );
+ static_assert( r.z == 0, "r.z == 0" );
+ }
+
+ {
+ constexpr std::array tp{{ 1, 2, 3 }};
+
+ constexpr auto r = make_from_tuple( tp );
+
+ static_assert( r.x == 1, "r.x == 1" );
+ static_assert( r.y == 2, "r.y == 2" );
+ static_assert( r.z == 3, "r.z == 3" );
+ }
+
+ {
+ constexpr std::tuple<> tp;
+
+ constexpr auto r = make_from_tuple( tp );
+
+ static_assert( r.x == 0, "r.x == 0" );
+ static_assert( r.y == 0, "r.y == 0" );
+ static_assert( r.z == 0, "r.z == 0" );
+ }
+}
+
+#endif