Make C++11 fusion::vector more consistent with C++03 fusion::vector

- Construct from elements is enabled iff each argument is_convertible to
    corresponding element.
  - Construct from sequence is enabled iff the single argument is a fusion
    sequence.
  - C++11 vector and tuple also disable construct from sequence that are
    shorter than the destination. C++03 gives incorrect is_convertible
    responses in this situation and fails to compile if that constructor is
    used; C++11 can have instantation errors in
    and_<is_convertible<U, T>...> without the additional check.
  - C++11 tuple and vector support truncation conversion and assignment like
    all other sequences.
This commit is contained in:
Lee Clagett
2016-08-21 16:59:04 -04:00
parent 55150a7fa6
commit 5906d9c316
22 changed files with 1504 additions and 283 deletions

View File

@ -0,0 +1,320 @@
/*=============================================================================
Copyright (c) 2016 Lee Clagett
Use modification and distribution are subject to the Boost Software
License, Version 1.0. (See accompanyintg file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt).
==============================================================================*/
#include <boost/config.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/fusion/adapted/boost_tuple.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
# include <boost/fusion/adapted/std_tuple.hpp>
#endif
#include <boost/fusion/container/deque.hpp>
#include <boost/fusion/container/list.hpp>
#include <boost/fusion/tuple.hpp>
#include <boost/fusion/container/vector.hpp>
#include "fixture.hpp"
template <template <typename> class Scenario>
void test()
{
using namespace test_detail;
// Note the trunction conversion tests from each containter
// ... bug or feature?
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(FUSION_SEQUENCE<int>(300), 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::push_back(FUSION_SEQUENCE<int>(200), 400)
, FUSION_SEQUENCE<convertible>(200)
)
));
BOOST_TEST((run<Scenario<FUSION_SEQUENCE<> > >(boost::fusion::vector<>())));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<> > >(
boost::fusion::vector<int>(100), boost::fusion::vector<>()
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::vector<int>(110)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::vector<int, int>(200, 100)
, boost::fusion::vector<convertible>(200)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::vector<int, int>(200, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::vector<int, int, int>(500, 400, 100)
, boost::fusion::vector<convertible, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::vector<int>(500), 400
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::vector<int, int>(500, 400), 100
)
, boost::fusion::vector<convertible, int>(500, 400)
)
));
BOOST_TEST((run<Scenario< FUSION_SEQUENCE<> > >(boost::fusion::deque<>())));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<> > >(
boost::fusion::deque<int>(100), boost::fusion::deque<>()
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::deque<int>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::deque<int, int>(500, 100)
, boost::fusion::deque<convertible>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::deque<int, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::deque<int, int, int>(500, 400, 100)
, boost::fusion::deque<convertible, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::deque<int>(500), 400
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::deque<int, int>(500, 400), 100
)
, boost::fusion::deque<convertible, int>(500, 400)
)
));
BOOST_TEST((run< Scenario< FUSION_SEQUENCE<> > >(boost::fusion::list<>())));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<> > >(
boost::fusion::list<int>(100), boost::fusion::list<>()
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::list<int>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::list<int, int>(500, 100)
, boost::fusion::list<convertible>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::list<int, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::list<int, int, int>(500, 400, 100)
, boost::fusion::list<convertible, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::list<int>(500), 400
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::list<int, int>(500, 400), 100
)
, boost::fusion::list<convertible, int>(500, 400)
)
));
BOOST_TEST((run<Scenario< FUSION_SEQUENCE<> > >(boost::fusion::tuple<>())));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<> > >(
boost::fusion::tuple<int>(100), boost::fusion::tuple<>()
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::tuple<int>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::fusion::tuple<int, int>(500, 100)
, boost::fusion::tuple<convertible>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::tuple<int, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::tuple<int, int, int>(500, 400, 100)
, boost::fusion::tuple<convertible, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::tuple<int>(500), 400
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::fusion::tuple<int, int>(500, 400), 100
)
, boost::fusion::tuple<convertible, int>(500, 400)
)
));
BOOST_TEST((run< Scenario< FUSION_SEQUENCE<> > >(boost::tuple<>())));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<> > >(
boost::tuple<int>(100), boost::tuple<>()
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::tuple<int>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
boost::tuple<int, int>(500, 100)
, boost::tuple<convertible>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::tuple<int, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::tuple<int, int, int>(500, 400, 100)
, boost::tuple<convertible, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(boost::tuple<int>(500), 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
boost::tuple<int, int>(500, 400), 100
)
, boost::tuple<convertible, int>(500, 400)
)
));
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_TEST((run< Scenario< FUSION_SEQUENCE<> > >(std::tuple<>())));
BOOST_TEST((
run<Scenario<FUSION_SEQUENCE<> > >(std::tuple<int>(100), std::tuple<>())
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
std::tuple<int>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
std::tuple<int, int>(500, 100)
, std::tuple<convertible>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
std::tuple<int, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
std::tuple<int, int, int>(500, 400, 100)
, std::tuple<convertible, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(std::tuple<int>(500), 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
boost::fusion::push_back(
std::tuple<int, int>(500, 400), 100
)
, std::tuple<convertible, int>(500, 400)
)
));
#endif
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
std::pair<int, int>(500, 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<> > >(
std::pair<int, int>(500, 400)
, boost::fusion::vector<>()
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
std::pair<int, int>(500, 400)
, boost::fusion::vector<convertible>(500)
)
));
}

View File

@ -5,6 +5,8 @@
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 <string>
#include <boost/detail/lightweight_test.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/mpl.hpp>
@ -15,6 +17,8 @@
#include <boost/mpl/equal.hpp>
#include <boost/static_assert.hpp>
#include "fixture.hpp"
#if !defined(FUSION_AT)
#define FUSION_AT at_c
#endif
@ -36,12 +40,6 @@ namespace test_detail
struct DD { operator CC() const { return CC(); }; };
}
boost::fusion::FUSION_SEQUENCE<double, double, double, double>
foo(int i)
{
return boost::fusion::FUSION_MAKE(i, i+1, i+2, i+3);
}
void test_mpl()
{
using namespace boost::fusion;
@ -60,6 +58,7 @@ void test_mpl()
BOOST_STATIC_ASSERT(equal::value);
}
template <template <typename> class Scenario>
void
test()
{
@ -77,6 +76,9 @@ test()
BOOST_TEST((double)FUSION_AT<0>(t1) == FUSION_AT<0>(t3));
BOOST_TEST(FUSION_AT<1>(t1) == FUSION_AT<1>(t3)[0]);
BOOST_TEST(FUSION_AT<0>(t1) == 4);
BOOST_TEST(FUSION_AT<1>(t1) == 'a');
// testing copy and assignment with implicit conversions
// between elements testing tie
@ -91,8 +93,62 @@ test()
BOOST_TEST(c=='a');
BOOST_TEST(d>5.4 && d<5.6);
// returning a tuple with conversion
foo(2);
test_mpl();
BOOST_TEST((run< Scenario< FUSION_SEQUENCE<> > >(FUSION_SEQUENCE<>())));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int> > >(FUSION_SEQUENCE<int>(500))
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
FUSION_SEQUENCE<int>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int> > >(
FUSION_SEQUENCE<int, int>(500, 100)
, FUSION_SEQUENCE<int>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible> > >(
FUSION_SEQUENCE<int, int>(500, 100)
, FUSION_SEQUENCE<convertible>(500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int, int> > >(
FUSION_SEQUENCE<int, int>(500, 600)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, int> > >(
FUSION_SEQUENCE<convertible, int>(100, 500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int, convertible> > >(
FUSION_SEQUENCE<int, convertible>(500, 600)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, convertible> > >(
FUSION_SEQUENCE<int, int>(400, 500)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int, int> > >(
FUSION_SEQUENCE<int, int, int>(500, 100, 323)
, FUSION_SEQUENCE<int, int>(500, 100)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<convertible, convertible> > >(
FUSION_SEQUENCE<int, int, int>(500, 600, 100)
, FUSION_SEQUENCE<convertible, convertible>(500, 600)
)
));
}

View File

@ -13,10 +13,30 @@
#define FUSION_SEQUENCE deque
#include "copy.hpp"
using namespace test_detail;
// c++11 deque has bug, cannot properly copy-assign from a const value
template <typename T>
struct skip_const_lvalue_assignment
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return
run< can_implicit_construct<T> >(source, expected) &&
run< can_construct<T> >(source, expected) &&
run< can_rvalue_assign<T> >(source, expected) &&
run< can_lvalue_assign<T> >(source, expected);
}
};
int
main()
{
test();
#if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE)
test<skip_const_lvalue_assignment>();
#else
test<can_copy>();
#endif
return boost::report_errors();
}

View File

@ -7,13 +7,37 @@
#include <boost/fusion/container/deque/deque.hpp>
#include <boost/core/lightweight_test.hpp>
#define FUSION_SEQUENCE deque
#define FUSION_SEQUENCE boost::fusion::deque
#include "nest.hpp"
/* deque has a few issues:
- sequence conversion constructor is explicit
- assignment sequence conversion has bug in base class
- c++11 direct assignment from lvalue has bug */
template <typename T>
struct skip_issues
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
using namespace test_detail;
return
#if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE)
run< can_construct<T> >(source, expected) &&
run< can_implicit_construct<T> >(source, expected) &&
run< can_rvalue_assign<T> >(source, expected) &&
run< can_convert_using<can_construct>::to<T> >(source, expected) &&
#else
run< can_copy<T> >(source, expected) &&
#endif
run< can_construct_from_elements<T> >(source, expected);
}
};
int
main()
{
test();
test<skip_issues>();
return boost::report_errors();
}

216
test/sequence/fixture.hpp Normal file
View File

@ -0,0 +1,216 @@
/*=============================================================================
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/fusion/sequence/comparison.hpp>
#include <boost/mpl/identity.hpp>
namespace test_detail
{
struct convertible
{
convertible() : value_() {}
convertible(int value) : value_(value) {}
int value_;
};
bool operator==(convertible const& lhs, convertible const& rhs)
{
return lhs.value_ == rhs.value_;
}
bool operator!=(convertible const& lhs, convertible const& rhs)
{
return lhs.value_ != rhs.value_;
}
// Testing conversion at function call allows for testing mutable lvalue,
// const lvalue, and rvalue as the source. mpl::identity prevents deduction
template <typename T>
T implicit_construct(typename boost::mpl::identity<T>::type source)
{
return source;
}
template <typename F, typename Source, typename Expected>
bool run(Source const& source, Expected const& expected)
{
return F()(source, expected);
}
template <typename F, typename Source>
bool run(Source const& source)
{
return run<F>(source, source);
}
template <typename T>
struct can_rvalue_implicit_construct
{
template<typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return expected == implicit_construct<T>(implicit_construct<Source>(source));
}
};
template <typename T>
struct can_lvalue_implicit_construct
{
template <typename Source, typename Expected>
bool operator()(Source source, Expected const& expected) const
{
return expected == implicit_construct<T>(source);
}
};
template <typename T>
struct can_const_lvalue_implicit_construct
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return expected == implicit_construct<T>(source);
}
};
template <typename T>
struct can_implicit_construct
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return
run< can_rvalue_implicit_construct<T> >(source, expected) &&
run< can_lvalue_implicit_construct<T> >(source, expected) &&
run< can_const_lvalue_implicit_construct<T> >(source, expected);
}
};
template <typename T>
struct can_rvalue_construct
{
template<typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return expected == T(implicit_construct<Source>(source));
}
};
template <typename T>
struct can_lvalue_construct
{
template <typename Source, typename Expected>
bool operator()(Source source, Expected const& expected) const
{
return expected == T(source);
}
};
template <typename T>
struct can_const_lvalue_construct
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return expected == T(source);
}
};
template <typename T>
struct can_construct
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return
run< can_rvalue_construct<T> >(source, expected) &&
run< can_lvalue_construct<T> >(source, expected) &&
run< can_const_lvalue_construct<T> >(source, expected);
}
};
template <typename T>
struct can_rvalue_assign
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
bool result = true;
{
T seq;
result &= (seq == expected || seq != expected);
seq = implicit_construct<Source>(source);
result &= (seq == expected);
}
return result;
}
};
template <typename T>
struct can_lvalue_assign
{
template <typename Source, typename Expected>
bool operator()(Source source, Expected const& expected) const
{
bool result = true;
{
T seq;
result &= (seq == expected || seq != expected);
seq = source;
result &= (seq == expected);
}
return result;
}
};
template <typename T>
struct can_const_lvalue_assign
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
bool result = true;
{
T seq;
result &= (seq == expected || seq != expected);
seq = source;
result &= (seq == expected);
}
return result;
}
};
template <typename T>
struct can_assign
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return
run< can_rvalue_assign<T> >(source, expected) &&
run< can_lvalue_assign<T> >(source, expected) &&
run< can_const_lvalue_assign<T> >(source, expected);
}
};
template <typename T>
struct can_copy
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
return
run< can_construct<T> >(source, expected) &&
run< can_implicit_construct<T> >(source, expected) &&
run< can_assign<T> >(source, expected);
}
};
} // test_detail

View File

@ -15,7 +15,7 @@
int
main()
{
test();
test<test_detail::can_copy>();
return boost::report_errors();
}

View File

@ -7,13 +7,30 @@
#include <boost/fusion/container/list/list.hpp>
#include <boost/core/lightweight_test.hpp>
#define FUSION_SEQUENCE list
#define FUSION_SEQUENCE boost::fusion::list
#include "nest.hpp"
/* list has a few issues:
- sequence conversion constructor has bug when first element is a sequence
- assignment sequence conversion has bug in base class */
template <typename T>
struct skip_issues
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
using namespace test_detail;
return
run< can_copy<T> >(source, expected) &&
run< can_construct_from_elements<T> >(source, expected);
}
};
int
main()
{
test();
test<skip_issues>();
return boost::report_errors();
}

View File

@ -7,111 +7,315 @@
#include <utility>
#include <boost/config.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/as_deque.hpp>
#include <boost/fusion/include/as_list.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/begin.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/value_of.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
template<typename C, template<typename> class As>
void test_from_sequence_rvalue()
#include "fixture.hpp"
namespace test_detail
{
typename As<C>::type dst((C()));
(void)dst;
}
struct adapted_sequence
{
adapted_sequence() : value_() {}
explicit adapted_sequence(int value) : value_(value) {}
int value_;
};
template<typename C, template<typename> class As>
void test_from_sequence_const_lvalue()
{
C src;
typename As<C>::type dst(src);
(void)dst;
}
bool operator==(adapted_sequence const& lhs, adapted_sequence const& rhs)
{
return lhs.value_ == rhs.value_;
}
template<typename C, template<typename> class As>
void test_from_sequence_lvalue()
{
const C src;
typename As<C>::type dst(src);
(void)dst;
}
bool operator!=(adapted_sequence const& lhs, adapted_sequence const& rhs)
{
return lhs.value_ != rhs.value_;
}
template<typename C, template<typename> class As>
void test_from_sequence()
{
// the following tests do not work in all cases for C++03
#if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
test_from_sequence_rvalue<C, As>();
test_from_sequence_const_lvalue<C, As>();
test_from_sequence_lvalue<C, As>();
#endif
}
template <template <typename> class Scenario>
struct can_convert_using
{
template <typename T>
struct to
{
static bool can_convert_(boost::true_type /* skip */)
{
return true;
}
template <typename C>
void test_copy()
{
C src;
C dst = src;
(void)dst;
}
static bool can_convert_(boost::false_type /* skip */)
{
using namespace boost::fusion;
return
run<Scenario<T> >(typename result_of::as_deque<T>::type()) &&
run<Scenario<T> >(typename result_of::as_list<T>::type()) &&
run<Scenario<T> >(typename result_of::as_vector<T>::type());
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename C>
void test_move()
{
C src;
C dst = std::move(src);
(void)dst;
}
#endif
template <typename Source, typename Expected>
bool operator()(Source const&, Expected const&) const
{
// bug when converting single element sequences in C++03 and
// C++11...
// not_<not_<is_convertible<sequence<sequence<int>>, int >
// is invalid check
typedef typename ::boost::fusion::result_of::size<T>::type seq_size;
return can_convert_(
boost::integral_constant<bool, seq_size::value == 1>()
);
}
};
};
template <typename C>
void test_all()
{
// as_deque and as_list do not work in C++03 or C++11 mode
// test_from_sequence<C, boost::fusion::result_of::as_deque>();
// test_from_sequence<C, boost::fusion::result_of::as_list>();
test_from_sequence<C, boost::fusion::result_of::as_vector>();
test_copy<C>();
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
test_move<C>();
#endif
}
template <typename T>
struct can_construct_from_elements
{
template <typename Source, typename Expected>
bool operator()(Source const&, Expected const&) const
{
// constructing a nested sequence of one is the complicated case to
// disambiguate from a conversion-copy, so focus on that
typedef typename boost::fusion::result_of::size<T>::type seq_size;
return can_construct_(
boost::integral_constant<int, seq_size::value>()
);
}
template <int Size>
static bool can_construct_(boost::integral_constant<int, Size>)
{
return Size == 0 || Size == 2 || Size == 3;
}
static bool can_construct_(boost::integral_constant<int, 1>)
{
typedef typename ::boost::remove_reference<
typename ::boost::remove_const<
typename ::boost::fusion::result_of::value_of<
typename ::boost::fusion::result_of::begin<T>::type
>::type
>::type
>::type element;
return run< can_construct<T> >(element(), T());
}
};
template <typename T>
struct can_nest
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected)
{
return
run< can_copy<T> >(source, expected);
run< can_convert_using<can_copy>::to<T> >(source, expected) &&
run< can_construct_from_elements<T> >(source, expected);
}
};
} // test_detail
BOOST_FUSION_ADAPT_STRUCT(test_detail::adapted_sequence, (int, data))
template <template <typename> class Scenario>
void
test()
{
using namespace boost::fusion;
using namespace test_detail;
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<> > >();
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<>, int> >();
test_all<FUSION_SEQUENCE<int, FUSION_SEQUENCE<> > >();
test_all<FUSION_SEQUENCE<int, FUSION_SEQUENCE<>, float> >();
BOOST_TEST(boost::fusion::traits::is_sequence<adapted_sequence>::value);
BOOST_TEST(boost::fusion::size(adapted_sequence()) == 1);
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<int> > >();
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, int> >();
test_all<FUSION_SEQUENCE<int, FUSION_SEQUENCE<int> > >();
test_all<FUSION_SEQUENCE<int, FUSION_SEQUENCE<int>, float> >();
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<> > > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<> >()
)
));
BOOST_TEST((
run< Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, int> > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<>, int>(FUSION_SEQUENCE<>(), 325)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<> > > >(
FUSION_SEQUENCE< int, FUSION_SEQUENCE<> >(325, FUSION_SEQUENCE<>())
)
));
BOOST_TEST((
run< Scenario<FUSION_SEQUENCE<int, FUSION_SEQUENCE<>, float> > >(
FUSION_SEQUENCE<int, FUSION_SEQUENCE<> , float>(
325, FUSION_SEQUENCE<>(), 2.0f
)
)
));
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<int, float> > >();
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<int, float>, int> >();
test_all<FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, float> > >();
test_all<FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, float>, float> >();
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<int> > > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(400))
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<adapted_sequence> > >(
FUSION_SEQUENCE<adapted_sequence>(adapted_sequence(400))
)
));
BOOST_TEST((
run< Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, int> > >(
FUSION_SEQUENCE<FUSION_SEQUENCE<int>, int>(
FUSION_SEQUENCE<int>(325), 400
)
)
));
BOOST_TEST((
run< Scenario<FUSION_SEQUENCE<adapted_sequence, int> > >(
FUSION_SEQUENCE<adapted_sequence, int>(adapted_sequence(325), 400)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE< int, FUSION_SEQUENCE<int> > > >(
FUSION_SEQUENCE< int, FUSION_SEQUENCE<int> >(
325, FUSION_SEQUENCE<int>(400)
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int, adapted_sequence> > >(
FUSION_SEQUENCE<int, adapted_sequence>(325, adapted_sequence(450))
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<int>, int> > >(
FUSION_SEQUENCE<int, FUSION_SEQUENCE<int>, int>(
500, FUSION_SEQUENCE<int>(350), 200
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<int, adapted_sequence, int> > >(
FUSION_SEQUENCE<int, adapted_sequence, int>(
300, adapted_sequence(500), 400)
)
));
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<> > >();
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<> > >();
test_all<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<int> > >();
test_all<
FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<float> >
>();
test_all<
FUSION_SEQUENCE<FUSION_SEQUENCE<int, float>, FUSION_SEQUENCE<float> >
>();
test_all<
FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<float, int> >
>();
test_all<
FUSION_SEQUENCE<
FUSION_SEQUENCE<int, float>, FUSION_SEQUENCE<float, int>
>
>();
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<int, int> > > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<int, int> >(
FUSION_SEQUENCE<int, int>(450, 500)
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE<FUSION_SEQUENCE<int, int>, int> > >(
FUSION_SEQUENCE<FUSION_SEQUENCE<int, int>, int>(
FUSION_SEQUENCE<int, int>(450, 500), 150
)
)
));
BOOST_TEST((
run< Scenario< FUSION_SEQUENCE< int, FUSION_SEQUENCE<int, int> > > >(
FUSION_SEQUENCE< int, FUSION_SEQUENCE<int, int> >(
450, FUSION_SEQUENCE<int, int>(500, 150)
)
)
));
BOOST_TEST((
run<Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, int>, int> > >(
FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, int>, int>(
150, FUSION_SEQUENCE<int, int>(250, 350), 450
)
)
));
BOOST_TEST((
run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<> > > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<>, FUSION_SEQUENCE<> >(
FUSION_SEQUENCE<>(), FUSION_SEQUENCE<>()
)
)
));
BOOST_TEST((
run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<> > > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<> >(
FUSION_SEQUENCE<int>(150), FUSION_SEQUENCE<>()
)
)
));
BOOST_TEST((
run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<int> > > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<>, FUSION_SEQUENCE<int> >(
FUSION_SEQUENCE<>(), FUSION_SEQUENCE<int>(500)
)
)
));
BOOST_TEST((
run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> > > >(
FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> >(
FUSION_SEQUENCE<int>(155), FUSION_SEQUENCE<int>(255)
)
)
));
BOOST_TEST((
run< Scenario<
FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int> >
> >(
FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int> >(
FUSION_SEQUENCE<int, int>(222, 333), FUSION_SEQUENCE<int>(444)
)
)
));
BOOST_TEST((
run< Scenario<
FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int, int> >
> >(
FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int, int> >(
FUSION_SEQUENCE<int>(100), FUSION_SEQUENCE<int, int>(300, 400)
)
)
));
BOOST_TEST((
run< Scenario<
FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> >
> >(
FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> >(
FUSION_SEQUENCE<int, int>(600, 700)
, FUSION_SEQUENCE<int, int>(800, 900)
)
)
));
// Ignore desired scenario, and cheat to make these work
BOOST_TEST((
run< can_lvalue_construct< FUSION_SEQUENCE<FUSION_SEQUENCE<>&> > >(
FUSION_SEQUENCE<>()
, FUSION_SEQUENCE< FUSION_SEQUENCE<> >()
)
));
BOOST_TEST((
run< can_construct< FUSION_SEQUENCE<const FUSION_SEQUENCE<>&> > >(
FUSION_SEQUENCE<>()
, FUSION_SEQUENCE< FUSION_SEQUENCE<> >()
)
));
BOOST_TEST((
run< can_lvalue_construct< FUSION_SEQUENCE<FUSION_SEQUENCE<int>&> > >(
FUSION_SEQUENCE<int>(300)
, FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(300))
)
));
BOOST_TEST((
run< can_construct< FUSION_SEQUENCE<const FUSION_SEQUENCE<int>&> > >(
FUSION_SEQUENCE<int>(400)
, FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(400))
)
));
}

251
test/sequence/traits.hpp Normal file
View File

@ -0,0 +1,251 @@
/*=============================================================================
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>
#include <boost/detail/lightweight_test.hpp>
#include <boost/fusion/container/list.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_constructible.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
struct convertible
{
convertible(int) {}
};
template <typename From, typename To>
bool is_convertible(bool has_conversion)
{
typedef typename boost::remove_reference<
typename boost::remove_const<From>::type
>::type from_rvalue;
typedef typename boost::add_reference<from_rvalue>::type from_lvalue;
typedef typename boost::add_const<from_lvalue>::type from_const_lvalue;
return
boost::is_convertible<from_rvalue, To>::value == has_conversion &&
boost::is_convertible<from_lvalue, To>::value == has_conversion &&
boost::is_convertible<from_const_lvalue, To>::value == has_conversion;
}
// is_constructible has a few requirements
#if !defined(BOOST_NO_CXX11_DECLTYPE) && \
!defined(BOOST_NO_CXX11_TEMPLATES) && \
!defined(BOOST_NO_SFINAE_EXPR)
#define FUSION_TEST_HAS_CONSTRUCTIBLE
template <typename To, typename... Args>
bool is_lvalue_constructible(bool has_constructor)
{
return has_constructor ==
boost::is_constructible<
To
, typename boost::add_reference<Args>::type...
>::value;
}
template <typename To, typename... Args>
bool is_constructible_impl(bool has_constructor)
{
return
boost::is_constructible<To, Args...>::value == has_constructor &&
is_lvalue_constructible<To, Args...>(has_constructor) &&
is_lvalue_constructible<
To, typename boost::add_const<Args>::type...
>(has_constructor);
}
template <typename To, typename... Args>
bool is_constructible(bool has_constructor)
{
return
is_constructible_impl<
To
, typename boost::remove_reference<
typename boost::remove_const<Args>::type
>::type...
>(has_constructor);
}
void test_constructible()
{
BOOST_TEST((is_constructible< FUSION_SEQUENCE<> >(true)));
BOOST_TEST((is_constructible< FUSION_SEQUENCE<int> >(true)));
BOOST_TEST((is_constructible<FUSION_SEQUENCE<int>, int>(true)));
BOOST_TEST((is_constructible<FUSION_SEQUENCE<convertible>, int>(true)));
BOOST_TEST((
is_constructible<FUSION_SEQUENCE<convertible>, convertible>(true)
));
BOOST_TEST((
is_constructible<FUSION_SEQUENCE<int, int>, int, int>(true)
));
BOOST_TEST((
is_constructible<FUSION_SEQUENCE<convertible, int>, int, int>(true)
));
BOOST_TEST((
is_constructible<
FUSION_SEQUENCE<convertible, int>, convertible, int
>(true)
));
BOOST_TEST((
is_constructible<FUSION_SEQUENCE<int, convertible>, int, int>(true)
));
BOOST_TEST((
is_constructible<
FUSION_SEQUENCE<int, convertible>, int, convertible
>(true)
));
BOOST_TEST((
is_constructible<
FUSION_SEQUENCE<convertible, convertible>, int, int
>(true)
));
BOOST_TEST((
is_constructible<
FUSION_SEQUENCE<convertible, convertible>, convertible, int
>(true)
));
BOOST_TEST((
is_constructible<
FUSION_SEQUENCE<convertible, convertible>, int, convertible
>(true)
));
BOOST_TEST((
is_constructible<
FUSION_SEQUENCE<convertible, convertible>, convertible, convertible
>(true)
));
}
#endif // is_constructible is available
void test_convertible(bool has_seq_conversion)
{
BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<> >(false)));
BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<int> >(false)));
BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<const int&> >(false)));
BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<convertible> >(false)));
BOOST_TEST((
is_convertible<int, FUSION_SEQUENCE<const convertible&> >(false)
));
BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<int, int> >(false)));
BOOST_TEST((
is_convertible<int, FUSION_SEQUENCE<const int&, const int&> >(false)
));
BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<convertible, int> >(false)));
BOOST_TEST((
is_convertible<int, FUSION_SEQUENCE<const convertible&, const int&> >(false)
));
BOOST_TEST((is_convertible<int, FUSION_SEQUENCE<int, convertible> >(false)));
BOOST_TEST((
is_convertible<int, FUSION_SEQUENCE<const int&, const convertible&> >(false)
));
BOOST_TEST((
is_convertible<int, FUSION_SEQUENCE<convertible, convertible> >(false)
));
BOOST_TEST((
is_convertible<
int, FUSION_SEQUENCE<const convertible&, const convertible&>
>(false)
));
BOOST_TEST((is_convertible<FUSION_SEQUENCE<>, FUSION_SEQUENCE<> >(true)));
BOOST_TEST((
is_convertible<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> >(true)
));
BOOST_TEST((
is_convertible<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<const int&> >(true)
));
BOOST_TEST((
is_convertible<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<convertible> >(true)
));
BOOST_TEST((
is_convertible<FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> >(true)
));
BOOST_TEST((
is_convertible<
FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<const int&, const int&>
>(true)
));
BOOST_TEST((
is_convertible<
FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<convertible, int>
>(true)
));
BOOST_TEST((
is_convertible<
FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, convertible>
>(true)
));
BOOST_TEST((
is_convertible<
FUSION_SEQUENCE<int, int>
, FUSION_SEQUENCE<convertible, convertible>
>(true)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<>, FUSION_SEQUENCE<>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int>, FUSION_SEQUENCE<int>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int>, FUSION_SEQUENCE<const int&>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int>, FUSION_SEQUENCE<convertible>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int, int>
, FUSION_SEQUENCE<const int&, const int&>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int, int>, FUSION_SEQUENCE<convertible, int>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int, int>, FUSION_SEQUENCE<int, convertible>
>(has_seq_conversion)
));
BOOST_TEST((
is_convertible<
FUSION_ALT_SEQUENCE<int, int>
, FUSION_SEQUENCE<convertible, convertible>
>(has_seq_conversion)
));
}

View File

@ -0,0 +1,51 @@
/*=============================================================================
Copyright (c) 2016 Lee Clagett
Use modification and distribution are subject to 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/tuple.hpp>
#define FUSION_SEQUENCE boost::fusion::tuple
#include "conversion.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
using namespace test_detail;
void test_tuple()
{
BOOST_TEST((
run< can_copy< boost::fusion::tuple<int, int> > >(
std::pair<int, int>(1, 9)
)
));
BOOST_TEST((
run< can_copy< boost::fusion::tuple<int, convertible> > >(
std::pair<int, int>(1, 9)
)
));
BOOST_TEST((
run< can_copy< boost::fusion::tuple<convertible, int> > >(
std::pair<int, int>(1, 9)
)
));
BOOST_TEST((
run< can_copy< boost::fusion::tuple<convertible, convertible> > >(
std::pair<int, int>(1, 9)
)
));
}
int main()
{
test<can_assign>(); // conversion construction not supported
test_tuple();
return boost::report_errors();
}

View File

@ -16,7 +16,7 @@
int
main()
{
test();
test<test_detail::can_copy>();
return boost::report_errors();
}

View File

@ -7,13 +7,29 @@
#include <boost/fusion/tuple/tuple.hpp>
#include <boost/core/lightweight_test.hpp>
#define FUSION_SEQUENCE tuple
#define FUSION_SEQUENCE boost::fusion::tuple
#include "nest.hpp"
// tuple does not support conversion construction from sequence by design
template <typename T>
struct skip_constructor_conversion
{
template <typename Source, typename Expected>
bool operator()(Source const& source, Expected const& expected) const
{
using namespace test_detail;
return
run< can_copy<T> >(source, expected) &&
run< can_convert_using<can_assign>::to<T> >(source, expected) &&
run< can_construct_from_elements<T> >(source, expected);
}
};
int
main()
{
test();
test<skip_constructor_conversion>();
return boost::report_errors();
}

View File

@ -11,15 +11,11 @@
#include <boost/type_traits/is_constructible.hpp>
#include <boost/type_traits/is_convertible.hpp>
struct test_conversion
{
test_conversion(int) {}
};
#define FUSION_SEQUENCE boost::fusion::tuple
#define FUSION_ALT_SEQUENCE boost::fusion::vector
#include "traits.hpp"
struct test_no_conversion
{
explicit test_no_conversion(int) {}
};
struct not_convertible {};
/* Some construction differences in fusion::tuple from std::tuple:
- Construction from elements cannot call an explicit constructor.
@ -35,89 +31,56 @@ struct test_no_conversion
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;
int
main()
{
using namespace boost::fusion;
BOOST_TEST(!(is_convertible<int, tuple<> >::value));
BOOST_TEST(!(is_convertible<int&, tuple<> >::value));
test_convertible(false /* no conversion construction */ );
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<std::pair<int, int>, tuple<int, int> >(true)));
BOOST_TEST((
is_convertible<std::pair<int, int>, tuple<convertible, int> >(true)
));
BOOST_TEST((
is_convertible<std::pair<int, int>, tuple<int, convertible> >(true)
));
BOOST_TEST((
is_convertible<
std::pair<int, int>, tuple<convertible, convertible>
>(true)
));
BOOST_TEST(!(is_convertible<int, tuple<int, int> >::value));
BOOST_TEST(!(is_convertible<int&, tuple<int, int> >::value));
}
#if defined(FUSION_TEST_HAS_CONSTRUCTIBLE)
test_constructible();
// 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<> >(true)));
BOOST_TEST((is_constructible<tuple<>, int>(false)));
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> >(true)));
BOOST_TEST((is_constructible<tuple<int>, int>(true)));
BOOST_TEST((is_constructible<tuple<convertible>, int>(true)));
BOOST_TEST((is_constructible<tuple<not_convertible>, int>(false)));
BOOST_TEST((is_constructible< tuple<int>, vector<int> >(false)));
BOOST_TEST((is_constructible<tuple<int>, int, int>(false)));
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
));
BOOST_TEST((is_constructible< tuple<int, int> >(true)));
BOOST_TEST((is_constructible<tuple<int, int>, int, int>(true)));
BOOST_TEST((
is_constructible<tuple<convertible, convertible>, int, int>(true)
));
BOOST_TEST((is_constructible<tuple<int, not_convertible>, int, int>(false)));
BOOST_TEST((is_constructible<tuple<not_convertible, int>, int, int>(false)));
BOOST_TEST((
is_constructible<tuple<not_convertible, not_convertible>, int, int>(false)
));
#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
));
}
// C++03 fusion::tuple has constructors that can never be used
BOOST_TEST((is_constructible<tuple<int, int>, int>(false)));
#endif
BOOST_TEST((is_constructible<tuple<int, int>, int, int, int>(false)));
#endif // FUSION_TEST_HAS_CONSTRUCTIBLE
return boost::report_errors();
}

View File

@ -0,0 +1,19 @@
/*=============================================================================
Copyright (c) 2016 Lee Clagett
Use modification and distribution are subject to 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>
#define FUSION_SEQUENCE boost::fusion::vector
#include "conversion.hpp"
int main()
{
test<test_detail::can_copy>();
return boost::report_errors();
}

View File

@ -15,7 +15,7 @@
int
main()
{
test();
test<test_detail::can_copy>();
return boost::report_errors();
}

View File

@ -7,13 +7,13 @@
#include <boost/fusion/container/vector/vector.hpp>
#include <boost/core/lightweight_test.hpp>
#define FUSION_SEQUENCE vector
#define FUSION_SEQUENCE boost::fusion::vector
#include "nest.hpp"
int
main()
{
test();
test<test_detail::can_nest>();
return boost::report_errors();
}

View File

@ -0,0 +1,32 @@
/*=============================================================================
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/list.hpp>
#include <boost/fusion/container/vector.hpp>
#define FUSION_SEQUENCE boost::fusion::vector
#define FUSION_ALT_SEQUENCE boost::fusion::list
#include "traits.hpp"
int main() {
test_convertible(true /* has conversion construction */ );
// C++11 models overly aggressive (bug) implicit conversion from C++03
BOOST_TEST((
is_convertible<
boost::fusion::list<int>
, boost::fusion::vector< boost::fusion::list<int> >
>(true)
));
#if defined(FUSION_TEST_HAS_CONSTRUCTIBLE)
test_constructible();
#endif
return boost::report_errors();
}