mirror of
https://github.com/boostorg/fusion.git
synced 2025-07-17 14:22:13 +02:00
Add DISABLE_VARIADIC_VECTOR and SFINAE for c++11 tuple element construction
This commit is contained in:
@ -15,6 +15,7 @@
|
|||||||
|| defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \
|
|| defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \
|
||||||
|| defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) \
|
|| defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) \
|
||||||
|| defined(BOOST_NO_CXX11_DECLTYPE)) \
|
|| defined(BOOST_NO_CXX11_DECLTYPE)) \
|
||||||
|
|| defined(BOOST_FUSION_DISABLE_VARIADIC_VECTOR) \
|
||||||
|| (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES))
|
|| (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES))
|
||||||
# if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
|
# if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
|
||||||
# undef BOOST_FUSION_HAS_VARIADIC_VECTOR
|
# undef BOOST_FUSION_HAS_VARIADIC_VECTOR
|
||||||
|
35
include/boost/fusion/support/detail/and.hpp
Normal file
35
include/boost/fusion/support/detail/and.hpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*=============================================================================
|
||||||
|
Copyright (c) 2016 Lee Clagett
|
||||||
|
|
||||||
|
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)
|
||||||
|
==============================================================================*/
|
||||||
|
#ifndef FUSION_AND_07152016_1625
|
||||||
|
#define FUSION_AND_07152016_1625
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/type_traits/integral_constant.hpp>
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||||
|
#error fusion::detail::and_ requires variadic templates
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace boost { namespace fusion { namespace detail {
|
||||||
|
template<typename ...Cond>
|
||||||
|
struct and_impl : false_type {};
|
||||||
|
|
||||||
|
template<typename ...T>
|
||||||
|
struct and_impl<integral_constant<T, true>...> : true_type {};
|
||||||
|
|
||||||
|
/* fusion::detail::and_ differs from mpl::and_ in the following ways:
|
||||||
|
- The empty set is valid and returns true
|
||||||
|
- A single element set is valid and returns the identity
|
||||||
|
- There is no upper bound on the set size
|
||||||
|
- The conditions are evaluated at once, and are not short-circuited. This
|
||||||
|
reduces instantations when returning true; the implementation is not
|
||||||
|
recursive. */
|
||||||
|
template<typename ...Cond>
|
||||||
|
struct and_ : and_impl<integral_constant<bool, Cond::value>...> {};
|
||||||
|
}}}
|
||||||
|
|
||||||
|
#endif // FUSION_AND_07152016_1625
|
@ -20,12 +20,15 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// C++11 interface
|
// C++11 interface
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <boost/core/enable_if.hpp>
|
||||||
#include <boost/fusion/container/vector/vector.hpp>
|
#include <boost/fusion/container/vector/vector.hpp>
|
||||||
#include <boost/fusion/sequence/intrinsic/size.hpp>
|
#include <boost/fusion/sequence/intrinsic/size.hpp>
|
||||||
#include <boost/fusion/sequence/intrinsic/value_at.hpp>
|
#include <boost/fusion/sequence/intrinsic/value_at.hpp>
|
||||||
#include <boost/fusion/sequence/intrinsic/at.hpp>
|
#include <boost/fusion/sequence/intrinsic/at.hpp>
|
||||||
#include <boost/fusion/sequence/comparison.hpp>
|
#include <boost/fusion/sequence/comparison.hpp>
|
||||||
#include <boost/fusion/sequence/io.hpp>
|
#include <boost/fusion/sequence/io.hpp>
|
||||||
|
#include <boost/fusion/support/detail/and.hpp>
|
||||||
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace boost { namespace fusion
|
namespace boost { namespace fusion
|
||||||
@ -49,13 +52,29 @@ namespace boost { namespace fusion
|
|||||||
tuple(tuple<U...>&& other)
|
tuple(tuple<U...>&& other)
|
||||||
: base_type(std::move(other)) {}
|
: base_type(std::move(other)) {}
|
||||||
|
|
||||||
template <typename ...U>
|
template <
|
||||||
|
typename ...U
|
||||||
|
, typename = typename boost::enable_if_c<(
|
||||||
|
fusion::detail::and_<is_convertible<U, T>...>::value &&
|
||||||
|
sizeof...(U) >= 1
|
||||||
|
)>::type
|
||||||
|
>
|
||||||
/*BOOST_CONSTEXPR*/ BOOST_FUSION_GPU_ENABLED
|
/*BOOST_CONSTEXPR*/ BOOST_FUSION_GPU_ENABLED
|
||||||
explicit
|
explicit
|
||||||
tuple(U&&... args)
|
tuple(U&&... args)
|
||||||
: base_type(std::forward<U>(args)...) {}
|
: base_type(std::forward<U>(args)...) {}
|
||||||
|
|
||||||
template <typename U>
|
template<typename U1, typename U2>
|
||||||
|
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||||
|
tuple(std::pair<U1, U2> const& other)
|
||||||
|
: base_type(other.first, other.second) {}
|
||||||
|
|
||||||
|
template<typename U1, typename U2>
|
||||||
|
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||||
|
tuple(std::pair<U1, U2>&& other)
|
||||||
|
: base_type(std::move(other.first), std::move(other.second)) {}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
|
||||||
tuple& operator=(U&& rhs)
|
tuple& operator=(U&& rhs)
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <boost/fusion/container/vector/detail/config.hpp>
|
#include <boost/fusion/container/vector/detail/config.hpp>
|
||||||
|
|
||||||
#if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) \
|
#if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) \
|
||||||
|
|| defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \
|
||||||
|| (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES))
|
|| (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES))
|
||||||
# if defined(BOOST_FUSION_HAS_VARIADIC_TUPLE)
|
# if defined(BOOST_FUSION_HAS_VARIADIC_TUPLE)
|
||||||
# undef BOOST_FUSION_HAS_VARIADIC_TUPLE
|
# undef BOOST_FUSION_HAS_VARIADIC_TUPLE
|
||||||
|
15
test/Jamfile
15
test/Jamfile
@ -131,6 +131,20 @@ project
|
|||||||
[ run sequence/tuple_nest.cpp : : : : ]
|
[ run sequence/tuple_nest.cpp : : : : ]
|
||||||
[ run sequence/tuple_hash.cpp : : : : ]
|
[ run sequence/tuple_hash.cpp : : : : ]
|
||||||
[ run sequence/tuple_tie.cpp : : : : ]
|
[ run sequence/tuple_tie.cpp : : : : ]
|
||||||
|
[
|
||||||
|
run sequence/tuple_traits.cpp
|
||||||
|
:
|
||||||
|
:
|
||||||
|
:
|
||||||
|
: sequence/tuple_traits/maybe_variadic_vector
|
||||||
|
]
|
||||||
|
[
|
||||||
|
run sequence/tuple_traits.cpp
|
||||||
|
:
|
||||||
|
:
|
||||||
|
: <define>BOOST_FUSION_DISABLE_VARIADIC_VECTOR
|
||||||
|
: sequence/tuple_traits/no_variadic_vector
|
||||||
|
]
|
||||||
[ run sequence/transform_view.cpp : : : : ]
|
[ run sequence/transform_view.cpp : : : : ]
|
||||||
[ run sequence/vector_comparison.cpp : : : : ]
|
[ run sequence/vector_comparison.cpp : : : : ]
|
||||||
[ run sequence/vector_construction.cpp : : : : ]
|
[ run sequence/vector_construction.cpp : : : : ]
|
||||||
@ -197,6 +211,7 @@ project
|
|||||||
[ compile support/pair_vector.cpp : : : : ]
|
[ compile support/pair_vector.cpp : : : : ]
|
||||||
[ compile support/pair_nest.cpp : : : : ]
|
[ compile support/pair_nest.cpp : : : : ]
|
||||||
[ compile support/index_sequence.cpp : : : : ]
|
[ compile support/index_sequence.cpp : : : : ]
|
||||||
|
[ compile support/and.cpp : : : : ]
|
||||||
|
|
||||||
# [ compile-fail xxx.cpp : : : : ]
|
# [ compile-fail xxx.cpp : : : : ]
|
||||||
|
|
||||||
|
@ -13,9 +13,37 @@
|
|||||||
#define FUSION_AT get
|
#define FUSION_AT get
|
||||||
#include "construction.hpp"
|
#include "construction.hpp"
|
||||||
|
|
||||||
|
// Bug in C++03 tuple? Cannot construct from a std::pair without including
|
||||||
|
// std::pair fusion adaption
|
||||||
|
#if !defined(BOOST_FUSION_HAS_VARIADIC_TUPLE)
|
||||||
|
# include <boost/fusion/adapted/std_pair.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct test_conversion
|
||||||
|
{
|
||||||
|
test_conversion(int value) : value_(value) {}
|
||||||
|
|
||||||
|
int value_;
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
test();
|
test();
|
||||||
|
|
||||||
|
{
|
||||||
|
using namespace boost::fusion;
|
||||||
|
const tuple<int, test_conversion> instance(std::pair<int, int>(1, 9));
|
||||||
|
BOOST_TEST(boost::fusion::get<0>(instance) == 1);
|
||||||
|
BOOST_TEST(boost::fusion::get<1>(instance).value_ == 9);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
using namespace boost::fusion;
|
||||||
|
const std::pair<int, int> init(16, 4);
|
||||||
|
const tuple<int, test_conversion> instance(init);
|
||||||
|
BOOST_TEST(boost::fusion::get<0>(instance) == 16);
|
||||||
|
BOOST_TEST(boost::fusion::get<1>(instance).value_ == 4);
|
||||||
|
}
|
||||||
|
|
||||||
return boost::report_errors();
|
return boost::report_errors();
|
||||||
}
|
}
|
||||||
|
123
test/sequence/tuple_traits.cpp
Normal file
123
test/sequence/tuple_traits.cpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*=============================================================================
|
||||||
|
Copyright (c) 2016 Lee Clagett
|
||||||
|
|
||||||
|
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 <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/fusion/container/vector.hpp>
|
||||||
|
#include <boost/fusion/tuple/tuple.hpp>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/type_traits/is_constructible.hpp>
|
||||||
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
|
||||||
|
struct test_conversion
|
||||||
|
{
|
||||||
|
test_conversion(int) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_no_conversion
|
||||||
|
{
|
||||||
|
explicit test_no_conversion(int) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Some construction differences in fusion::tuple from std::tuple:
|
||||||
|
- Construction from elements cannot call an explicit constructor.
|
||||||
|
- There is no implicit construction from elements.
|
||||||
|
- Construction from std::pair is _enabled_ when tuple is not of size 2.
|
||||||
|
- Construction from tuple is _enabled_ when destination tuple is of
|
||||||
|
different size.
|
||||||
|
- Implicit construction from std::pair can call explicit constructors on
|
||||||
|
elements.
|
||||||
|
- Implicit construction from tuple can call explicit constructors on
|
||||||
|
elements.
|
||||||
|
|
||||||
|
These differences are historical. Matching the behavior of std::tuple
|
||||||
|
could break existing code, however, switching to fusion::vector would
|
||||||
|
restore the historical behavior. */
|
||||||
|
int
|
||||||
|
main() {
|
||||||
|
{
|
||||||
|
using namespace boost;
|
||||||
|
using namespace boost::fusion;
|
||||||
|
|
||||||
|
BOOST_TEST(!(is_convertible<int, tuple<> >::value));
|
||||||
|
BOOST_TEST(!(is_convertible<int&, tuple<> >::value));
|
||||||
|
|
||||||
|
BOOST_TEST(!(is_convertible< int, tuple<int> >::value));
|
||||||
|
BOOST_TEST(!(is_convertible< int&, tuple<int> >::value));
|
||||||
|
BOOST_TEST(!(is_convertible< vector<int>, tuple<int> >::value));
|
||||||
|
BOOST_TEST(!(is_convertible< vector<int>&, tuple<int> >::value));
|
||||||
|
|
||||||
|
BOOST_TEST(!(is_convertible<int, tuple<int, int> >::value));
|
||||||
|
BOOST_TEST(!(is_convertible<int&, tuple<int, int> >::value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// is_constructible has some restrictions ...
|
||||||
|
#if !(defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TEMPLATES) || \
|
||||||
|
defined(BOOST_NO_SFINAE_EXPR))
|
||||||
|
{
|
||||||
|
using namespace boost;
|
||||||
|
using namespace boost::fusion;
|
||||||
|
|
||||||
|
BOOST_TEST((is_constructible< tuple<> >::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<>, int>::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<>, int&>::value));
|
||||||
|
|
||||||
|
BOOST_TEST((is_constructible< tuple<int> >::value));
|
||||||
|
BOOST_TEST((is_constructible<tuple<int>, int>::value));
|
||||||
|
BOOST_TEST((is_constructible<tuple<int>, int&>::value));
|
||||||
|
BOOST_TEST((is_constructible<tuple<test_conversion>, int>::value));
|
||||||
|
BOOST_TEST((is_constructible<tuple<test_conversion>, int&>::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<test_no_conversion>, int>::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<test_no_conversion>, int&>::value));
|
||||||
|
BOOST_TEST(!(is_constructible< tuple<int>, vector<int> >::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<int>, vector<int>&>::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<int>, int, int>::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<int>, int&, int&>::value));
|
||||||
|
|
||||||
|
BOOST_TEST((is_constructible< tuple<int, int> >::value));
|
||||||
|
BOOST_TEST((is_constructible<tuple<int, int>, int, int>::value));
|
||||||
|
BOOST_TEST((is_constructible<tuple<int, int>, int&, int&>::value));
|
||||||
|
BOOST_TEST((
|
||||||
|
is_constructible<
|
||||||
|
tuple<test_conversion, test_conversion>
|
||||||
|
, int
|
||||||
|
, int
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
BOOST_TEST((
|
||||||
|
is_constructible<
|
||||||
|
tuple<test_conversion, test_conversion>
|
||||||
|
, int&
|
||||||
|
, int&
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
BOOST_TEST(!(
|
||||||
|
is_constructible<
|
||||||
|
tuple<test_no_conversion, test_no_conversion>
|
||||||
|
, int
|
||||||
|
, int
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
BOOST_TEST(!(
|
||||||
|
is_constructible<
|
||||||
|
tuple<test_no_conversion, test_no_conversion>
|
||||||
|
, int&
|
||||||
|
, int&
|
||||||
|
>::value
|
||||||
|
));
|
||||||
|
#if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
|
||||||
|
// C++03 fusion::tuple has constructors that can never be used
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<int, int>, int>::value));
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<int, int>, int&>::value));
|
||||||
|
#endif
|
||||||
|
BOOST_TEST(!(is_constructible<tuple<int, int>, int, int, int>::value));
|
||||||
|
BOOST_TEST(!(
|
||||||
|
is_constructible<tuple<int, int>, int&, int&, int&>::value
|
||||||
|
));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
33
test/support/and.cpp
Normal file
33
test/support/and.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*=============================================================================
|
||||||
|
Copyright (c) 2016 Lee Clagett
|
||||||
|
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 <boost/config.hpp>
|
||||||
|
|
||||||
|
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||||
|
|
||||||
|
#include <boost/detail/lightweight_test.hpp>
|
||||||
|
#include <boost/fusion/support/detail/and.hpp>
|
||||||
|
#include <boost/mpl/bool.hpp>
|
||||||
|
#include <boost/type_traits/integral_constant.hpp>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
using namespace boost;
|
||||||
|
using namespace boost::fusion::detail;
|
||||||
|
|
||||||
|
BOOST_TEST((and_<>::value));
|
||||||
|
BOOST_TEST(!(and_<false_type>::value));
|
||||||
|
BOOST_TEST((and_<true_type>::value));
|
||||||
|
BOOST_TEST(!(and_<true_type, false_type>::value));
|
||||||
|
BOOST_TEST((and_<true_type, true_type>::value));
|
||||||
|
BOOST_TEST(!(and_<true_type, true_type, false_type>::value));
|
||||||
|
BOOST_TEST((and_<true_type, true_type, true_type>::value));
|
||||||
|
BOOST_TEST((and_<true_type, mpl::true_>::value));
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Reference in New Issue
Block a user