diff options
Diffstat (limited to 'src/boost/libs/type_erasure')
79 files changed, 10351 insertions, 0 deletions
diff --git a/src/boost/libs/type_erasure/build/Jamfile.v2 b/src/boost/libs/type_erasure/build/Jamfile.v2 new file mode 100644 index 000000000..2408e6bd8 --- /dev/null +++ b/src/boost/libs/type_erasure/build/Jamfile.v2 @@ -0,0 +1,17 @@ +# Boost.TypeErasure library +# +# Copyright 2015 Steven Watanabe +# +# 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) + +project /boost/type_erasure + : source-location ../src + : requirements <link>shared:<define>BOOST_TYPE_ERASURE_DYN_LINK + : usage-requirements <link>shared:<define>BOOST_TYPE_ERASURE_DYN_LINK +; + +lib boost_type_erasure : dynamic_binding.cpp /boost//thread /boost//system ; + +boost-install boost_type_erasure ; diff --git a/src/boost/libs/type_erasure/example/Jamfile.jam b/src/boost/libs/type_erasure/example/Jamfile.jam new file mode 100644 index 000000000..d96922f46 --- /dev/null +++ b/src/boost/libs/type_erasure/example/Jamfile.jam @@ -0,0 +1,24 @@ +# Boost.TypeErasure library +# +# Copyright 2011 Steven Watanabe +# +# 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) + +import testing ; + +compile basic.cpp ; +compile multi.cpp ; +compile convert.cpp ; +compile references.cpp ; +compile custom.cpp ; +compile construction.cpp ; +compile concept_map.cpp ; +compile compose.cpp ; +compile overload.cpp ; +compile associated.cpp ; + +run print_sequence.cpp ; +run printf.cpp ; +run multifunction.cpp ; diff --git a/src/boost/libs/type_erasure/example/associated.cpp b/src/boost/libs/type_erasure/example/associated.cpp new file mode 100644 index 000000000..ca4ef26e4 --- /dev/null +++ b/src/boost/libs/type_erasure/example/associated.cpp @@ -0,0 +1,147 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/deduced.hpp> +#include <boost/type_erasure/same_type.hpp> +#include <boost/pointee.hpp> +#include <boost/mpl/vector.hpp> +#include <iostream> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +//[associated1 +/*` + Associated types such as `typename T::value_type` or + `typename std::iterator_traits<T>::reference` are + quite common in template programming. + Boost.TypeErasure handles them using the __deduced + template. __deduced is just like an ordinary + __placeholder, except that the type that it binds + to is determined by calling a metafunction and + does not need to be specified explicitly. + + For example, we can define a concept for + holding an iterator, raw pointer, or + smart pointer as follows. + First, we define a metafunction called `pointee` + defining the associated type. +*/ + +template<class T> +struct pointee +{ + typedef typename mpl::eval_if<is_placeholder<T>, + mpl::identity<void>, + boost::pointee<T> + >::type type; +}; + +/*` + Note that we can't just use `boost::pointee`, because + this metafunction needs to be safe to instantiate + with placeholders. It doesn't matter what it returns + as long as it doesn't give an error. (The library + never tries to instantiate it with a placeholder, but + argument dependent lookup can cause spurious instantiations.) +*/ + +template<class T = _self> +struct pointer : + mpl::vector< + copy_constructible<T>, + dereferenceable<deduced<pointee<T> >&, T> + > +{ + // provide a typedef for convenience + typedef deduced<pointee<T> > element_type; +}; + +//] + +void associated2() { + //[associated2 + /*` + Now the Concept of `x` uses two placeholders, `_self` + and `pointer<>::element_type`. When we construct `x`, + with an `int*`, `pointer<>::element_type` is deduced + as `pointee<int*>::type` which is `int`. Thus, dereferencing + `x` returns an __any that contains an `int`. + */ + int i = 10; + any< + mpl::vector< + pointer<>, + typeid_<pointer<>::element_type> + > + > x(&i); + int j = any_cast<int>(*x); // j == i + //] +} + +void associated3() { + //[associated3 + /*` + Sometimes we want to require that the associated + type be a specific type. This can be solved using + the __same_type concept. Here we create an any that + can hold any pointer whose element type is `int`. + */ + int i = 10; + any< + mpl::vector< + pointer<>, + same_type<pointer<>::element_type, int> + > + > x(&i); + std::cout << *x << std::endl; // prints 10 + /*` + Using __same_type like this effectively causes the library to + replace all uses of `pointer<>::element_type` with `int` + and validate that it is always bound to `int`. + Thus, dereferencing `x` now returns an `int`. + */ + //] +} + +void associated4() { + //[associated4 + /*` + __same_type can also be used for two placeholders. + This allows us to use a simple name instead of + writing out an associated type over and over. + */ + int i = 10; + any< + mpl::vector< + pointer<>, + same_type<pointer<>::element_type, _a>, + typeid_<_a>, + copy_constructible<_a>, + addable<_a>, + ostreamable<std::ostream, _a> + > + > x(&i); + std::cout << (*x + *x) << std::endl; // prints 20 + //] +} + +//[associated +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/associated.cpp associated.cpp]) +//` [associated1] +//` [associated2] +//` [associated3] +//` [associated4] +//] diff --git a/src/boost/libs/type_erasure/example/basic.cpp b/src/boost/libs/type_erasure/example/basic.cpp new file mode 100644 index 000000000..5b5ba102b --- /dev/null +++ b/src/boost/libs/type_erasure/example/basic.cpp @@ -0,0 +1,154 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/member.hpp> +#include <boost/type_erasure/free.hpp> +#include <boost/mpl/vector.hpp> +#include <iostream> +#include <vector> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +void basic1() { + //[basic1 + /*` + The main class in the library is __any. An __any can + store objects that meet whatever requirements we specify. + These requirements are passed to __any as an MPL sequence. + + [note The MPL sequence combines multiple concepts. + In the rare case when we only want a single concept, it doesn't + need to be wrapped in an MPL sequence.] + */ + any<mpl::vector<copy_constructible<>, typeid_<>, relaxed> > x(10); + int i = any_cast<int>(x); // i == 10 + /*` + __copy_constructible is a builtin concept that allows us to + copy and destroy the object. __typeid_ provides run-time + type information so that we can use __any_cast. __relaxed + enables various useful defaults. Without __relaxed, + __any supports /exactly/ what you specify and nothing else. + In particular, it allows default construction and assignment of __any. + */ + //] +} + +void basic2() { + //[basic2 + /*` + Now, this example doesn't do very much. `x` is approximately + equivalent to a [@boost:/libs/any/index.html boost::any]. + We can make it more interesting by adding some operators, + such as `operator++` and `operator<<`. + */ + any< + mpl::vector< + copy_constructible<>, + typeid_<>, + incrementable<>, + ostreamable<> + > + > x(10); + ++x; + std::cout << x << std::endl; // prints 11 + //] +} + +//[basic3 +/*` + The library provides concepts for most C++ operators, but this + obviously won't cover all use cases; we often need to + define our own requirements. Let's take the `push_back` + member, defined by several STL containers. +*/ + +BOOST_TYPE_ERASURE_MEMBER(push_back) + +void append_many(any<has_push_back<void(int)>, _self&> container) { + for(int i = 0; i < 10; ++i) + container.push_back(i); +} + +/*` + We use the macro __BOOST_TYPE_ERASURE_MEMBER + to define a concept called `has_push_back`. + When we use `has_push_back`, we have to + tell it the signature of the function, `void(int)`. + This means that the type we store in the any + has to have a member that looks like: + + `` + void push_back(int); + `` + + Thus, we could call `append_many` with `std::vector<int>`, + `std::list<int>`, or `std::vector<long>` (because `int` is + convertible to `long`), but not `std::list<std::string>` + or `std::set<int>`. + + Also, note that `append_many` has to operate directly + on its argument. It cannot make a copy. To handle this + we use `_self&` as the second argument of __any. `_self` + is a __placeholder. By using `_self&`, we indicate that + the __any stores a reference to an external object instead of + allocating its own object. +*/ + +/*` + Member functions can be const. + */ +BOOST_TYPE_ERASURE_MEMBER(empty) +bool is_empty(any<has_empty<bool() const>, const _self&> x) { + return x.empty(); +} + +/*` + For free functions, we can use the macro __BOOST_TYPE_ERASURE_FREE. +*/ + +BOOST_TYPE_ERASURE_FREE(getline) +std::vector<std::string> read_lines(any<has_getline<bool(_self&, std::string&)>, _self&> stream) +{ + std::vector<std::string> result; + std::string tmp; + while(getline(stream, tmp)) + result.push_back(tmp); + return result; +} + +/*` + The use of `has_getline` is very similar to `has_push_back` above. + The difference is that the placeholder `_self` is passed in + the function signature instead of as a separate argument. + + The __placeholder doesn't have to be the first argument. + We could just as easily make it the second argument. +*/ + + +void read_line(any<has_getline<bool(std::istream&, _self&)>, _self&> str) +{ + getline(std::cin, str); +} + +//] + +//[basic +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/basic.cpp basic.cpp]) +//` [basic1] +//` [basic2] +//` [basic3] +//] diff --git a/src/boost/libs/type_erasure/example/compose.cpp b/src/boost/libs/type_erasure/example/compose.cpp new file mode 100644 index 000000000..5a629af49 --- /dev/null +++ b/src/boost/libs/type_erasure/example/compose.cpp @@ -0,0 +1,44 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/mpl/vector.hpp> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +//[compose1 +/*` + Multiple concepts can be composed using an MPL sequence. +*/ +template<class T = _self> +struct arithmetic : + mpl::vector< + copy_constructible<T>, + addable<T>, + subtractable<T>, + multipliable<T>, + dividable<T>, + equality_comparable<T>, + less_than_comparable<T> + > +{}; +/*` + Now, `arithmetic` is a concept that can be used just + like any of the base concepts. +*/ +//] + +//[compose +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/compose.cpp compose.cpp]) +//` [compose1] +//] diff --git a/src/boost/libs/type_erasure/example/concept_map.cpp b/src/boost/libs/type_erasure/example/concept_map.cpp new file mode 100644 index 000000000..e35ef11db --- /dev/null +++ b/src/boost/libs/type_erasure/example/concept_map.cpp @@ -0,0 +1,50 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/operators.hpp> +#include <typeinfo> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +//[concept_map1 +/*` + Sometimes it is useful to non-intrusively adapt a + type to model a concept. For example, suppose that + we want to make `std::type_info` model __less_than_comparable. + To do this, we simply specialize the concept definition. +*/ +namespace boost { +namespace type_erasure { + +template<> +struct less_than_comparable<std::type_info> +{ + static bool apply(const std::type_info& lhs, const std::type_info& rhs) + { return lhs.before(rhs) != 0; } +}; + +} +} + +/*` + [note Most, but not all of the builtin concepts can be specialized. + Constructors, destructors, and RTTI need special treatment from the + library and cannot be specialized. Only primitive concepts can + be specialized, so the iterator concepts are also out.] +*/ + +//] + +//[concept_map +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/concept_map.cpp concept_map.cpp]) +//` [concept_map1] +//] diff --git a/src/boost/libs/type_erasure/example/construction.cpp b/src/boost/libs/type_erasure/example/construction.cpp new file mode 100644 index 000000000..1a9d327d9 --- /dev/null +++ b/src/boost/libs/type_erasure/example/construction.cpp @@ -0,0 +1,93 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/binding_of.hpp> +#include <string> +#include <vector> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +void construction1() { + //[construction1 + /*` + The library provides the __constructible concept to + allow an __any to capture constructors. The single + template argument should be a function signature. + The return type must be a placeholder specifying + the type to be constructed. The arguments are + the arguments of the constructor. + */ + typedef mpl::vector< + copy_constructible<_a>, + copy_constructible<_b>, + copy_constructible<_c>, + constructible<_a(const _b&, const _c&)> + > construct; + + typedef mpl::map< + mpl::pair<_a, std::vector<double> >, + mpl::pair<_b, std::size_t>, + mpl::pair<_c, double> + > types; + + any<construct, _b> size(std::size_t(10), make_binding<types>()); + any<construct, _c> val(2.5, make_binding<types>()); + any<construct, _a> v(size, val); + // v holds std::vector<double>(10, 2.5); + //] +} + +void construction3() { + //[construction3 + /*` + Now, suppose that we want a default constructor? + We can't have the default constructor of __any + call the default constructor of the contained type, + because it would have no way of knowing what the + contained type is. So, we'll need to pass + the placeholder binding information explicitly. + */ + typedef mpl::vector< + copy_constructible<>, + constructible<_self()> + > construct; + + any<construct> x(std::string("Test")); + any<construct> y(binding_of(x)); // y == "" + //] +} + +void construction4() { + //[construction4 + /*` + This method is not restricted to the default constructor. If + the constructor takes arguments, they can be passed after the + bindings. + */ + typedef mpl::vector< + copy_constructible<>, + constructible<_self(std::size_t, char)> + > construct; + + any<construct> x(std::string("Test")); + any<construct> y(binding_of(x), 5, 'A'); + //] +} + +//[construction +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/construction.cpp construction.cpp]) +//` [construction1] +//` [construction3] +//` [construction4] +//] diff --git a/src/boost/libs/type_erasure/example/convert.cpp b/src/boost/libs/type_erasure/example/convert.cpp new file mode 100644 index 000000000..e97613c19 --- /dev/null +++ b/src/boost/libs/type_erasure/example/convert.cpp @@ -0,0 +1,59 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <ostream> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +void convert1() { +//[convert1 + /*` + An __any can be converted to another __any + as long as the conversion is an "upcast." + */ + + typedef any< + mpl::vector< + copy_constructible<>, + typeid_<>, + ostreamable<> + > + > any_printable; + typedef any< + mpl::vector< + copy_constructible<>, + typeid_<> + > + > common_any; + any_printable x(10); + common_any y(x); + + /*` + This conversion is okay because the requirements of `common_any` + are a subset of the requirements of `any_printable`. Conversion + in the other direction is illegal. + + `` + common_any x(10); + any_printable y(x); // error + `` + */ +//] +} + +//[convert +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/convert.cpp convert.cpp]) +//` [convert1] +//] diff --git a/src/boost/libs/type_erasure/example/custom.cpp b/src/boost/libs/type_erasure/example/custom.cpp new file mode 100644 index 000000000..9ded58294 --- /dev/null +++ b/src/boost/libs/type_erasure/example/custom.cpp @@ -0,0 +1,107 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/concept_interface.hpp> +#include <boost/type_erasure/rebind_any.hpp> +#include <vector> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +//[custom1 +/*` + Earlier, we used __BOOST_TYPE_ERASURE_MEMBER to define + a concept for containers that support `push_back`. Sometimes + this interface isn't flexible enough, however. The library + also provides a lower level interface that gives full + control of the behavior. Let's take a look at what we + would need in order to define `has_push_back.` First, + we need to define the `has_push_back` template itself. We'll + give it two template parameters, one for the container + and one for the element type. This template must have + a static member function called apply which is used + to execute the operation. +*/ + +template<class C, class T> +struct has_push_back +{ + static void apply(C& cont, const T& arg) { cont.push_back(arg); } +}; +//] + +//[custom3 +/*` + Our second task is to customize __any so that we can call `c.push_back(10)`. + We do this by specializing __concept_interface. + The first argument is `has_push_back`, since we want to inject a member + into every __any that uses the `has_push_back` concept. The second argument, + `Base`, is used by the library to chain multiple uses of __concept_interface + together. We have to inherit from it publicly. `Base` is also used + to get access to the full __any type. The third argument is the placeholder + that represents this any. If someone used `push_back<_c, _b>`, + we only want to insert a `push_back` member in the container, + not the value type. Thus, the third argument is the container + placeholder. + + When we define `push_back` the argument type uses the metafunction + __as_param. This is just to handle the case where `T` is a + placeholder. If `T` is not a placeholder, then the metafunction + just returns its argument, `const T&`, unchanged. +*/ +namespace boost { +namespace type_erasure { +template<class C, class T, class Base> +struct concept_interface<has_push_back<C, T>, Base, C> : Base +{ + void push_back(typename as_param<Base, const T&>::type arg) + { call(has_push_back<C, T>(), *this, arg); } +}; +} +} +//] + +void custom2() { + //[custom2 + /*` + Now, we can use this in an __any using + __call to dispatch the operation. + */ + std::vector<int> vec; + any<has_push_back<_self, int>, _self&> c(vec); + int i = 10; + call(has_push_back<_self, int>(), c, i); + // vec is [10]. + //] +} + +void custom4() { + //[custom4 + /*` + Our example now becomes + */ + std::vector<int> vec; + any<has_push_back<_self, int>, _self&> c(vec); + c.push_back(10); + /*` + which is what we want. + */ + //] +} + +//[custom +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/custom.cpp custom.cpp]) +//` [custom1] +//` [custom2] +//` [custom3] +//` [custom4] +//] diff --git a/src/boost/libs/type_erasure/example/multi.cpp b/src/boost/libs/type_erasure/example/multi.cpp new file mode 100644 index 000000000..d34e0da49 --- /dev/null +++ b/src/boost/libs/type_erasure/example/multi.cpp @@ -0,0 +1,116 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/mpl/vector.hpp> +#include <iostream> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +void multi1() { + //[multi1 + /*` + Operations can have more than one __any argument. + Let's use binary addition as an example. + */ + typedef any< + mpl::vector< + copy_constructible<>, + typeid_<>, + addable<>, + ostreamable<> + > + > any_type; + any_type x(10); + any_type y(7); + any_type z(x + y); + std::cout << z << std::endl; // prints 17 + /*` + This is /not/ a multimethod. The underlying types of the + arguments of `+` must be the same or the behavior is undefined. + This example is correct because the arguments both hold + `int`'s. + + [note Adding __relaxed leads an exception rather than undefined + behavior if the argument types are wrong.] + */ + //] +} + +void multi2() { + //[multi2 + /*` + __addable`<>` requires the types of the arguments to be exactly + the same. This doesn't cover all uses of addition though. For + example, pointer arithmetic takes a pointer and an integer and + returns a pointer. We can capture this kind of relationship among + several types by identifying each type involved with a placeholder. + We'll let the placeholder `_a` represent the pointer and the + placeholder `_b` represent the integer. + */ + + int array[5]; + + typedef mpl::vector< + copy_constructible<_a>, + copy_constructible<_b>, + typeid_<_a>, + addable<_a, _b, _a> + > requirements; + + /*` + Our new concept, `addable<_a, _b, _a>` captures the + rules of pointer addition: `_a + _b -> _a`. + + Also, we can no longer capture the variables + independently. + `` + any<requirements, _a> ptr(&array[0]); // illegal + `` + This doesn't work because the library needs + to know the type that _b binds to when it + captures the concept bindings. We need to + specify the bindings of both placeholders + when we construct the __any. + */ + + typedef mpl::map<mpl::pair<_a, int*>, mpl::pair<_b, int> > types; + any<requirements, _a> ptr(&array[0], make_binding<types>()); + any<requirements, _b> idx(2, make_binding<types>()); + any<requirements, _a> x(ptr + idx); + // x now holds array + 2 + + /*` + Now that the arguments of `+` aren't the same type, + we require that both arguments agree that `_a` maps + to `int*` and that `_b` maps to `int`. + + We can also use __tuple to avoid having to + write out the map out explicitly. __tuple is + just a convenience class that combines the + placeholder bindings it gets from all its arguments. + */ + tuple<requirements, _a, _b> t(&array[0], 2); + any<requirements, _a> y(get<0>(t) + get<1>(t)); + //] +} + + +//[multi +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/multi.cpp multi.cpp]) +//` [multi1] +//` [multi2] +//] diff --git a/src/boost/libs/type_erasure/example/multifunction.cpp b/src/boost/libs/type_erasure/example/multifunction.cpp new file mode 100644 index 000000000..e2d5d1c9b --- /dev/null +++ b/src/boost/libs/type_erasure/example/multifunction.cpp @@ -0,0 +1,105 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +//[multifunction +/*` + (For the source of this example see + [@boost:/libs/type_erasure/example/multifunction.cpp multifunction.cpp]) + + This example implements an extension of Boost.Function that supports + multiple signatures. + + [note This example uses C++11 features. You'll need a + recent compiler for it to work.] + */ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/callable.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/variant.hpp> +#include <boost/phoenix/core.hpp> +#include <boost/phoenix/operator.hpp> +#include <boost/range/algorithm.hpp> +#include <algorithm> +#include <vector> +#include <string> +#include <iostream> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; +namespace phoenix = boost::phoenix; + +// First of all we'll declare the multifunction template. +// multifunction is like Boost.Function but instead of +// taking one signature, it takes any number of them. +template<class... Sig> +using multifunction = + any< + mpl::vector< + copy_constructible<>, + typeid_<>, + relaxed, + callable<Sig>... + > + >; + +// Let's use multifunction to process a variant. We'll start +// by defining a simple recursive variant to use. +typedef boost::make_recursive_variant< + int, + double, + std::string, + std::vector<boost::recursive_variant_> >::type variant_type; +typedef std::vector<variant_type> vector_type; + +// Now we'll define a multifunction that can operate +// on the leaf nodes of the variant. +typedef multifunction<void(int), void(double), void(std::string)> function_type; + +class variant_handler +{ +public: + void handle(const variant_type& arg) + { + boost::apply_visitor(impl, arg); + } + void set_handler(function_type f) + { + impl.f = f; + } +private: + // A class that works with boost::apply_visitor + struct dispatcher : boost::static_visitor<void> + { + // used for the leaves + template<class T> + void operator()(const T& t) { f(t); } + // For a vector, we recursively operate on the elements + void operator()(const vector_type& v) + { + boost::for_each(v, boost::apply_visitor(*this)); + } + function_type f; + }; + dispatcher impl; +}; + +int main() { + variant_handler x; + x.set_handler(std::cout << phoenix::val("Value: ") << phoenix::placeholders::_1 << std::endl); + + x.handle(1); + x.handle(2.718); + x.handle("The quick brown fox jumps over the lazy dog."); + x.handle(vector_type{ 1.618, "Gallia est omnis divisa in partes tres", 42 }); +} + +//] diff --git a/src/boost/libs/type_erasure/example/overload.cpp b/src/boost/libs/type_erasure/example/overload.cpp new file mode 100644 index 000000000..dcd69ba85 --- /dev/null +++ b/src/boost/libs/type_erasure/example/overload.cpp @@ -0,0 +1,165 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/concept_interface.hpp> +#include <boost/type_erasure/param.hpp> +#include <boost/type_erasure/derived.hpp> +#include <boost/type_erasure/is_placeholder.hpp> +#include <boost/utility/enable_if.hpp> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +//[overload1 +/*` + __concept_interface allows us to inject arbitrary declarations + into an __any. This is very flexible, but there are some pitfalls + to watch out for. Sometimes we want to use the same concept several + times with different parameters. Specializing __concept_interface + in a way that handles overloads correctly is a bit tricky. + Given a concept foo, we'd like the following to work: + + `` + any< + mpl::vector< + foo<_self, int>, + foo<_self, double>, + copy_constructible<> + > + > x = ...; + x.foo(1); // calls foo(int) + x.foo(1.0); // calls foo(double) + `` + + Because __concept_interface creates a linear + inheritance chain, without some extra work, + one overload of foo will hide the other. + + Here are the techniques that I found work reliably. + + For member functions I couldn't find a way to + avoid using two specializations. +*/ + +template<class T, class U> +struct foo +{ + static void apply(T& t, const U& u) { t.foo(u); } +}; + +namespace boost { +namespace type_erasure { + +template<class T, class U, class Base, class Enable> +struct concept_interface< ::foo<T, U>, Base, T, Enable> : Base +{ + typedef void _fun_defined; + void foo(typename as_param<Base, const U&>::type arg) + { + call(::foo<T, U>(), *this, arg); + } +}; + +template<class T, class U, class Base> +struct concept_interface< ::foo<T, U>, Base, T, typename Base::_fun_defined> : Base +{ + using Base::foo; + void foo(typename as_param<Base, const U&>::type arg) + { + call(::foo<T, U>(), *this, arg); + } +}; + +} +} + +/*` + This uses SFINAE to detect whether a using declaration is + needed. Note that the fourth argument of __concept_interface + is a dummy parameter which is always void and is + intended to be used for SFINAE. + Another solution to the problem that I've used + in the past is to inject a dummy declaration of `fun` + and always put in a using declaration. This is an + inferior solution for several reasons. It requires an + extra interface to add the dummy overload. It also + means that `fun` is always overloaded, even if the + user only asked for one overload. This makes it + harder to take the address of fun. + + Note that while using SFINAE requires some code + to be duplicated, the amount of code that has to + be duplicated is relatively small, since the implementation + of __concept_interface is usually a one liner. It's + a bit annoying, but I believe it's an acceptable cost + in lieu of a better solution. +*/ + +//] +//[overload2 +/*` + For free functions you can use inline friends. +*/ + +template<class T, class U> +struct bar_concept +{ + static void apply(T& t, const U& u) { bar(t, u); } +}; + +namespace boost { +namespace type_erasure { + +template<class T, class U, class Base> +struct concept_interface< ::bar_concept<T, U>, Base, T> : Base +{ + friend void bar(typename derived<Base>::type& t, typename as_param<Base, const U&>::type u) + { + call(::bar_concept<T, U>(), t, u); + } +}; + +template<class T, class U, class Base> +struct concept_interface< ::bar_concept<T, U>, Base, U, typename boost::disable_if<is_placeholder<T> >::type> : Base +{ + using Base::bar; + friend void bar(T& t, const typename derived<Base>::type& u) + { + call(::bar_concept<T, U>(), t, u); + } +}; + +} +} + +/*` + Basically we have to specialize __concept_interface once for + each argument to make sure that an overload is injected into + the first argument that's a placeholder. + As you might have noticed, the argument types are a bit tricky. + In the first specialization, the first argument uses __derived + instead of __as_param. The reason for this is that if we used + __as_param, then we could end up violating the one definition + rule by defining the same function twice. Similarly, we use + SFINAE in the second specialization to make sure that bar is + only defined once when both arguments are placeholders. It's + possible to merge the two specializations with a bit of metaprogramming, + but unless you have a lot of arguments, it's probably not + worth while. +*/ + +//] + +//[overload +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/overload.cpp overload.cpp]) +//` [overload1] +//` [overload2] +//] diff --git a/src/boost/libs/type_erasure/example/print_sequence.cpp b/src/boost/libs/type_erasure/example/print_sequence.cpp new file mode 100644 index 000000000..e977a7977 --- /dev/null +++ b/src/boost/libs/type_erasure/example/print_sequence.cpp @@ -0,0 +1,248 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +//[print_sequence + +/*` + (For the source of this example see + [@boost:/libs/type_erasure/example/print_sequence.cpp print_sequence.cpp]) + + This example defines a class hierarchy that allows a sequence + to be formatted in several different ways. We'd like to be + able to handle any sequence and any stream type, since the + range formatting is independent of the formatting of + individual elements. Thus, our interface needs to look + something like this: + + `` + class abstract_printer { + public: + template<class CharT, class Traits, class Range> + virtual void print(std::basic_ostream<CharT, Traits>& os, const Range& r) const = 0; + }; + `` + + Unfortunately, this is illegal because a virtual function + cannot be a template. However, we can define a + class with much the same behavior using Boost.TypeErasure. +*/ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/iterator.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/same_type.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <iostream> +#include <iomanip> +#include <vector> + +using namespace boost::type_erasure; + +struct _t : placeholder {}; +struct _iter : placeholder {}; +struct _os : placeholder {}; + +template<class T, class U = _self> +struct base_and_derived +{ + static T& apply(U& arg) { return arg; } +}; + +namespace boost { +namespace type_erasure { + +template<class T, class U, class Base> +struct concept_interface<base_and_derived<T, U>, Base, U> : Base +{ + operator typename rebind_any<Base, const T&>::type() const + { + return call(base_and_derived<T, U>(), const_cast<concept_interface&>(*this)); + } + operator typename rebind_any<Base, T&>::type() + { + return call(base_and_derived<T, U>(), *this); + } +}; + +} +} + +// abstract_printer - An abstract base class for formatting sequences. +class abstract_printer { +public: + // print - write a sequence to a std::ostream in a manner + // specific to the derived class. + // + // Requires: Range must be a Forward Range whose elements can be + // printed to os. + template<class CharT, class Traits, class Range> + void print(std::basic_ostream<CharT, Traits>& os, const Range& r) const { + // Capture the arguments + typename boost::range_iterator<const Range>::type + first(boost::begin(r)), + last(boost::end(r)); + tuple<requirements, _os&, _iter, _iter> args(os, first, last); + // and forward to the real implementation + do_print(get<0>(args), get<1>(args), get<2>(args)); + } + virtual ~abstract_printer() {} +protected: + // define the concept requirements of the arguments of + // print and typedef the any types. + typedef boost::mpl::vector< + base_and_derived<std::ios_base, _os>, + ostreamable<_os, _t>, + ostreamable<_os, const char*>, + forward_iterator<_iter, const _t&>, + same_type<_t, forward_iterator<_iter, const _t&>::value_type> + > requirements; + typedef boost::type_erasure::any<requirements, _os&> ostream_type; + typedef boost::type_erasure::any<requirements, _iter> iterator_type; + // do_print - This method must be implemented by derived classes + virtual void do_print( + ostream_type os, iterator_type first, iterator_type last) const = 0; +}; + +// separator_printer - writes the elements of a sequence +// separated by a fixed string. For example, if +// the separator is ", " separator_printer produces +// a comma separated list. +class separator_printer : public abstract_printer { +public: + explicit separator_printer(const std::string& sep) : separator(sep) {} +protected: + virtual void do_print( + ostream_type os, iterator_type first, iterator_type last) const { + if(first != last) { + os << *first; + ++first; + for(; first != last; ++first) { + os << separator.c_str() << *first; + } + } + } +private: + std::string separator; +}; + +// column_separator_printer - like separator_printer, but +// also inserts a line break after every n elements. +class column_separator_printer : public abstract_printer { +public: + column_separator_printer(const std::string& sep, std::size_t num_columns) + : separator(sep), + cols(num_columns) + {} +protected: + virtual void do_print( + ostream_type os, iterator_type first, iterator_type last) const { + std::size_t count = 0; + for(; first != last; ++first) { + os << *first; + boost::type_erasure::any<requirements, _iter> temp = first; + ++temp; + if(temp != last) { + os << separator.c_str(); + } + if(++count % cols == 0) { + os << "\n"; + } + } + } +private: + std::string separator; + std::size_t cols; +}; + +// aligned_column_printer - formats a sequence in columns +// reading down. For example, given the sequence +// { 1, 2, 3, 4, 5 }, aligned_column_printer might print +// 1 4 +// 2 5 +// 3 +class aligned_column_printer : public abstract_printer { +public: + aligned_column_printer(std::size_t column_width, std::size_t num_columns) + : width(column_width), + cols(num_columns) + {} +protected: + virtual void do_print( + ostream_type os, iterator_type first, iterator_type last) const + { + if(first == last) return; + std::vector<iterator_type> column_iterators; + + // find the tops of the columns + std::size_t count = 0; + for(iterator_type iter = first; iter != last; ++iter) { + ++count; + } + std::size_t rows = (count + cols - 1) / cols; + count = 0; + for(iterator_type iter = first; iter != last; ++iter) { + if(count % rows == 0) { + column_iterators.push_back(iter); + } + ++count; + } + + iterator_type last_col = column_iterators.back(); + + // print the full rows + while(column_iterators.back() != last) { + for(std::vector<iterator_type>::iterator + iter = column_iterators.begin(), + end = column_iterators.end(); iter != end; ++iter) + { + static_cast<std::ios_base&>(os).width(width); + os << **iter; + ++*iter; + } + os << "\n"; + } + + // print the rows that are missing the last column + column_iterators.pop_back(); + if(!column_iterators.empty()) { + while(column_iterators.back() != last_col) { + for(std::vector<iterator_type>::iterator + iter = column_iterators.begin(), + end = column_iterators.end(); iter != end; ++iter) + { + static_cast<std::ios_base&>(os).width(width); + os << **iter; + ++*iter; + } + os << "\n"; + } + } + } +private: + std::size_t width; + std::size_t cols; +}; + +int main() { + int test[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + separator_printer p1(","); + p1.print(std::cout, test); + std::cout << std::endl; + column_separator_printer p2(",", 4); + p2.print(std::cout, test); + std::cout << std::endl; + aligned_column_printer p3(16, 4); + p3.print(std::cout, test); +} + +//] diff --git a/src/boost/libs/type_erasure/example/printf.cpp b/src/boost/libs/type_erasure/example/printf.cpp new file mode 100644 index 000000000..c9dbc08a9 --- /dev/null +++ b/src/boost/libs/type_erasure/example/printf.cpp @@ -0,0 +1,293 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +//[printf +/*` + (For the source of this example see + [@boost:/libs/type_erasure/example/printf.cpp printf.cpp]) + + This example uses the library to implement a type safe printf. + + [note This example uses C++11 features. You'll need a + recent compiler for it to work.] + */ + +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/any.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/io/ios_state.hpp> +#include <iostream> +#include <sstream> +#include <iomanip> +#include <vector> +#include <string> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; +using namespace boost::io; + +// We capture the arguments by reference and require nothing +// except that each one must provide a stream insertion operator. +typedef any< + mpl::vector< + typeid_<>, + ostreamable<> + >, + const _self& +> any_printable; +typedef std::vector<any_printable> print_storage; + +// Forward declaration of the implementation function +void print_impl(std::ostream& os, const char * format, const print_storage& args); + +// print +// +// Writes values to a stream like the classic C printf function. The +// arguments are formatted based on specifiers in the format string, +// which match the pattern: +// +// '%' [ argument-number '$' ] flags * [ width ] [ '.' precision ] [ type-code ] format-specifier +// +// Other characters in the format string are written to the stream unchanged. +// In addition the sequence, "%%" can be used to print a literal '%' character. +// Each component is explained in detail below +// +// argument-number: +// The value must be between 1 and sizeof... T. It indicates the +// index of the argument to be formatted. If no index is specified +// the arguments will be processed sequentially. If an index is +// specified for one argument, then it must be specified for every argument. +// +// flags: +// Consists of zero or more of the following: +// '-': Left justify the argument +// '+': Print a plus sign for positive integers +// '0': Use leading 0's to pad instead of filling with spaces. +// ' ': If the value doesn't begin with a sign, prepend a space +// '#': Print 0x or 0 for hexadecimal and octal numbers. +// +// width: +// Indicates the minimum width to print. This can be either +// an integer or a '*'. an asterisk means to read the next +// argument (which must have type int) as the width. +// +// precision: +// For numeric arguments, indicates the number of digits to print. For +// strings (%s) the precision indicates the maximum number of characters +// to print. Longer strings will be truncated. As with width +// this can be either an integer or a '*'. an asterisk means +// to read the next argument (which must have type int) as +// the width. If both the width and the precision are specified +// as '*', the width is read first. +// +// type-code: +// This is ignored, but provided for compatibility with C printf. +// +// format-specifier: +// Must be one of the following characters: +// d, i, u: The argument is formatted as a decimal integer +// o: The argument is formatted as an octal integer +// x, X: The argument is formatted as a hexadecimal integer +// p: The argument is formatted as a pointer +// f: The argument is formatted as a fixed point decimal +// e, E: The argument is formatted in exponential notation +// g, G: The argument is formatted as either fixed point or using +// scientific notation depending on its magnitude +// c: The argument is formatted as a character +// s: The argument is formatted as a string +// +template<class... T> +void print(std::ostream& os, const char * format, const T&... t) +{ + // capture the arguments + print_storage args = { any_printable(t)... }; + // and forward to the real implementation + print_impl(os, format, args); +} + +// This overload of print with no explicit stream writes to std::cout. +template<class... T> +void print(const char * format, const T&... t) +{ + print(std::cout, format, t...); +} + +// The implementation from here on can be separately compiled. + +// utility function to parse an integer +int parse_int(const char *& format) { + int result = 0; + while(char ch = *format) { + switch(ch) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + result = result * 10 + (ch - '0'); + break; + default: return result; + } + ++format; + } + return result; +} + +// printf implementation +void print_impl(std::ostream& os, const char * format, const print_storage& args) { + int idx = 0; + ios_flags_saver savef_outer(os, std::ios_base::dec); + bool has_positional = false; + bool has_indexed = false; + while(char ch = *format++) { + if (ch == '%') { + if (*format == '%') { os << '%'; continue; } + + ios_flags_saver savef(os); + ios_precision_saver savep(os); + ios_fill_saver savefill(os); + + int precision = 0; + bool pad_space = false; + bool pad_zero = false; + + // parse argument index + if (*format != '0') { + int i = parse_int(format); + if (i != 0) { + if(*format == '$') { + idx = i - 1; + has_indexed = true; + ++format; + } else { + os << std::setw(i); + has_positional = true; + goto parse_precision; + } + } else { + has_positional = true; + } + } else { + has_positional = true; + } + + // Parse format modifiers + while((ch = *format)) { + switch(ch) { + case '-': os << std::left; break; + case '+': os << std::showpos; break; + case '0': pad_zero = true; break; + case ' ': pad_space = true; break; + case '#': os << std::showpoint << std::showbase; break; + default: goto parse_width; + } + ++format; + } + + parse_width: + int width; + if (*format == '*') { + ++format; + width = any_cast<int>(args.at(idx++)); + } else { + width = parse_int(format); + } + os << std::setw(width); + + parse_precision: + if (*format == '.') { + ++format; + if (*format == '*') { + ++format; + precision = any_cast<int>(args.at(idx++)); + } else { + precision = parse_int(format); + } + os << std::setprecision(precision); + } + + // parse (and ignore) the type modifier + switch(*format) { + case 'h': ++format; if(*format == 'h') ++format; break; + case 'l': ++format; if(*format == 'l') ++format; break; + case 'j': + case 'L': + case 'q': + case 't': + case 'z': + ++format; break; + } + + std::size_t truncate = 0; + + // parse the format code + switch(*format++) { + case 'd': case 'i': case 'u': os << std::dec; break; + case 'o': os << std::oct; break; + case 'p': case 'x': os << std::hex; break; + case 'X': os << std::uppercase << std::hex; break; + case 'f': os << std::fixed; break; + case 'e': os << std::scientific; break; + case 'E': os << std::uppercase << std::scientific; break; + case 'g': break; + case 'G': os << std::uppercase; break; + case 'c': case 'C': break; + case 's': case 'S': truncate = precision; os << std::setprecision(6); break; + default: assert(!"Bad format string"); + } + + if (pad_zero && !(os.flags() & std::ios_base::left)) { + os << std::setfill('0') << std::internal; + pad_space = false; + } + + if (truncate != 0 || pad_space) { + // These can't be handled by std::setw. Write to a stringstream and + // pad/truncate manually. + std::ostringstream oss; + oss.copyfmt(os); + oss << args.at(idx++); + std::string data = oss.str(); + + if (pad_space) { + if (data.empty() || (data[0] != '+' && data[0] != '-' && data[0] != ' ')) { + os << ' '; + } + } + if (truncate != 0 && data.size() > truncate) { + data.resize(truncate); + } + os << data; + } else { + os << args.at(idx++); + } + + // we can't have both positional and indexed arguments in + // the format string. + assert(has_positional ^ has_indexed); + + } else { + std::cout << ch; + } + } +} + +int main() { + print("int: %d\n", 10); + print("int: %0#8X\n", 0xA56E); + print("double: %g\n", 3.14159265358979323846); + print("double: %f\n", 3.14159265358979323846); + print("double: %+20.9e\n", 3.14159265358979323846); + print("double: %0+20.9g\n", 3.14159265358979323846); + print("double: %*.*g\n", 20, 5, 3.14159265358979323846); + print("string: %.10s\n", "Hello World!"); + print("double: %2$*.*g int: %1$d\n", 10, 20, 5, 3.14159265358979323846); +} + +//] diff --git a/src/boost/libs/type_erasure/example/references.cpp b/src/boost/libs/type_erasure/example/references.cpp new file mode 100644 index 000000000..a5ba69e5f --- /dev/null +++ b/src/boost/libs/type_erasure/example/references.cpp @@ -0,0 +1,142 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/shared_ptr.hpp> +#include <iostream> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +void references1() { + //[references1 + /*` + To capture by reference, we simply add a reference + to the __placeholder. + */ + int i; + any<typeid_<>, _self&> x(i); + any_cast<int&>(x) = 5; // now i is 5 + /*` + [note `_self` is the default __placeholder, so it is + easiest to use `_self&`. We could use another + __placeholder instead. __any`<`__typeid_`<_a>, _a&>` has + exactly the same behavior.] + */ + //] +} + +void references2() { + //[references2 + /*` + References cannot be rebound. Just like a built-in C++ reference, + once you've initialized it you can't change it to point to + something else. + `` + int i, j; + any<typeid_<>, _self&> x(i), y(j); + x = y; // error + `` + + [note As with any other operation, `x = y` for references + acts on `i` and `j`. Assignment like this is legal + if __assignable`<>` is in the Concept, but `x` would + still hold a reference to `i`.] + */ + //] +} + +void references3() { + //[references3 + /*` + A reference can be bound to another __any. + */ + typedef mpl::vector< + copy_constructible<>, + incrementable<> + > requirements; + + any<requirements> x(10); + any<requirements, _self&> y(x); + ++y; // x is now 11 + //] +} + +void references4() { + //[references4 + /*` + If a reference is used after the underlying object + goes out of scope or is reset, the behavior is undefined. + */ + typedef mpl::vector< + copy_constructible<>, + incrementable<>, + relaxed + > requirements; + any<requirements> x(10); + any<requirements, _self&> y(x); + x = 1.0; + ++y; // undefined behavior. + //] +} + +void references5() { + typedef mpl::vector< + copy_constructible<>, + incrementable<> + > requirements; + //[references5 + /*` + This only applies when a reference is constructed + from a value. If a reference is constructed from another + reference, the new reference does not depend on the old one. + */ + any<requirements> x(10); + boost::shared_ptr<any<requirements, _self&> > p( + new any<requirements, _self&>(x)); + any<requirements, _self&> y(*p); // equivalent to y(x); + p.reset(); + ++y; // okay + //] +} + +void references6() { + //[references6 + /*` + Both const and non-const references are supported. + */ + int i = 0; + any<incrementable<>, _self&> x(i); + any<incrementable<>, const _self&> y(x); + /*` + A reference to non-const can be converted to a reference + to const, but not the other way around. Naturally, + we can't apply mutating operations to a const reference. + + any<incrementable<>, _self&> z(y); // error + ++y; // error + */ + //] +} + +//[references +//` (For the source of the examples in this section see +//` [@boost:/libs/type_erasure/example/references.cpp references.cpp]) +//` [references1] +//` [references2] +//` [references3] +//` [references4] +//` [references5] +//` [references6] +//] diff --git a/src/boost/libs/type_erasure/index.html b/src/boost/libs/type_erasure/index.html new file mode 100644 index 000000000..319dc65de --- /dev/null +++ b/src/boost/libs/type_erasure/index.html @@ -0,0 +1,20 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=../../doc/html/boost_typeerasure.html"> +</head> +<body> +Automatic redirection failed, please go to +<a href="../../doc/html/boost_typeerasure.html">../../doc/html/boost_typeerasure.html</a> +<hr> +<tt> +Boost.TypeErasure<br> +<br> +Copyright (C) 2011 Steven Watanabe <br> +<br> +Distributed under the Boost Software License, Version 1.0. (See +accompanying file LICENSE_1_0.txt or copy at +<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br> +<br> +</tt> +</body> +</html> diff --git a/src/boost/libs/type_erasure/meta/libraries.json b/src/boost/libs/type_erasure/meta/libraries.json new file mode 100644 index 000000000..024afaa40 --- /dev/null +++ b/src/boost/libs/type_erasure/meta/libraries.json @@ -0,0 +1,14 @@ +{ + "key": "type_erasure", + "name": "Type Erasure", + "authors": [ + "Steven Watanabe" + ], + "description": "Runtime polymorphism based on concepts.", + "category": [ + "Data" + ], + "maintainers": [ + "Steven Watanabe <steven -at- providere-consulting.com>" + ] +} diff --git a/src/boost/libs/type_erasure/src/dynamic_binding.cpp b/src/boost/libs/type_erasure/src/dynamic_binding.cpp new file mode 100644 index 000000000..77c590935 --- /dev/null +++ b/src/boost/libs/type_erasure/src/dynamic_binding.cpp @@ -0,0 +1,57 @@ +// Boost.TypeErasure library +// +// Copyright 2015 Steven Watanabe +// +// 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) +// +// $Id$ + +#define BOOST_TYPE_ERASURE_SOURCE + +#include <boost/type_erasure/register_binding.hpp> +#include <boost/thread/shared_mutex.hpp> +#include <boost/thread/lock_types.hpp> +#include <map> +#include <utility> + +namespace { + +using ::boost::type_erasure::detail::key_type; +using ::boost::type_erasure::detail::value_type; + +typedef ::std::map<key_type, void(*)()> map_type; +typedef ::boost::shared_mutex mutex_type; + +// std::pair can have problems on older implementations +// when it tries to use the copy constructor of the mutex. +struct data_type +{ + map_type first; + mutex_type second; +}; + +data_type * get_data() { + static data_type result; + return &result; +} + +} + +BOOST_TYPE_ERASURE_DECL void boost::type_erasure::detail::register_function_impl(const key_type& key, value_type fn) { + ::data_type * data = ::get_data(); + ::boost::unique_lock<mutex_type> lock(data->second); + data->first.insert(std::make_pair(key, fn)); +} + +BOOST_TYPE_ERASURE_DECL value_type boost::type_erasure::detail::lookup_function_impl(const key_type& key) { + ::data_type * data = ::get_data(); + ::boost::shared_lock<mutex_type> lock(data->second); + ::map_type::const_iterator pos = data->first.find(key); + if(pos != data->first.end()) { + return pos->second; + } else { + throw bad_any_cast(); + } +} diff --git a/src/boost/libs/type_erasure/test/Jamfile.jam b/src/boost/libs/type_erasure/test/Jamfile.jam new file mode 100644 index 000000000..6515838ed --- /dev/null +++ b/src/boost/libs/type_erasure/test/Jamfile.jam @@ -0,0 +1,83 @@ +# Boost.TypeErasure library +# +# Copyright 2011 Steven Watanabe +# +# 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) + +import testing ; +import ../../../libs/config/checks/config ; + +run test_binding.cpp /boost//unit_test_framework ; +run test_increment.cpp /boost//unit_test_framework ; +run test_add.cpp /boost//unit_test_framework ; +run test_add_assign.cpp /boost//unit_test_framework ; +run test_callable.cpp /boost//unit_test_framework ; +run test_reference.cpp /boost//unit_test_framework ; +run test_construct.cpp /boost//unit_test_framework ; +run test_relaxed.cpp /boost//unit_test_framework ; +run test_assign.cpp /boost//unit_test_framework ; +run test_construct_ref.cpp /boost//unit_test_framework ; +run test_construct_cref.cpp /boost//unit_test_framework ; +run test_any_cast.cpp /boost//unit_test_framework ; +run test_binding_of.cpp /boost//unit_test_framework ; +run test_typeid_of.cpp /boost//unit_test_framework ; +run test_nested.cpp /boost//unit_test_framework ; +run test_less.cpp /boost//unit_test_framework ; +run test_equal.cpp /boost//unit_test_framework ; +run test_negate.cpp /boost//unit_test_framework ; +run test_dereference.cpp /boost//unit_test_framework ; +run test_subscript.cpp /boost//unit_test_framework ; +run test_forward_iterator.cpp /boost//unit_test_framework ; +run test_tuple.cpp /boost//unit_test_framework ; +run test_stream.cpp /boost//unit_test_framework ; +run test_deduced.cpp /boost//unit_test_framework ; +run test_same_type.cpp /boost//unit_test_framework ; +run test_member.cpp /boost//unit_test_framework ; +run test_null.cpp /boost//unit_test_framework ; +run test_free.cpp /boost//unit_test_framework ; +run test_is_empty.cpp /boost//unit_test_framework ; +run test_dynamic_any_cast.cpp /boost//unit_test_framework /boost//type_erasure ; +run test_limits.cpp /boost//unit_test_framework + : requirements + [ config.requires cxx11_rvalue_references + cxx11_template_aliases + cxx11_variadic_templates ] + <toolset>msvc-12.0:<build>no + <toolset>msvc-14.0:<build>no + ; + +compile test_param.cpp ; +compile test_is_subconcept.cpp ; +compile test_sfinae.cpp ; +compile test_interface_order.cpp ; +compile test_is_placeholder.cpp ; + +compile-fail fail_default_construct.cpp ; +compile-fail fail_construct_mismatch.cpp ; +compile-fail fail_construct_mismatch_ref.cpp ; +compile-fail fail_construct_mismatch_cref.cpp ; +compile-fail fail_construct_mismatch_rref.cpp ; +compile-fail fail_binding_convert_no_mapping.cpp ; +compile-fail fail_increment_discard_const.cpp ; +compile-fail fail_not_incrementable.cpp ; + +compile-fail fail_ref_assign.cpp ; +compile-fail fail_cref_assign.cpp ; +compile-fail fail_rref_assign.cpp ; + +compile-fail fail_ref_discard_const.cpp ; +compile-fail fail_ref_discard_const_convert.cpp ; +compile-fail fail_ref_discard_const_convert_ref.cpp ; +compile-fail fail_ref_discard_const_convert_cref.cpp ; +compile-fail fail_ref_discard_const_init.cpp ; + +compile-fail fail_any_cast_discard_const1.cpp ; +compile-fail fail_any_cast_discard_const2.cpp ; +compile-fail fail_any_cast_discard_const3.cpp ; +compile-fail fail_any_cast_discard_const4.cpp ; +compile-fail fail_any_cast_discard_const5.cpp ; +compile-fail fail_any_cast_discard_const6.cpp ; +compile-fail fail_any_cast_pointer_to_ref.cpp ; +compile-fail fail_any_cast_pointer_to_val.cpp ; diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_discard_const1.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const1.cpp new file mode 100644 index 000000000..ec8b1803c --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const1.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + const any< ::boost::mpl::vector<copy_constructible<>, typeid_<> > > y(2); + int i = any_cast<int&>(y); +} diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_discard_const2.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const2.cpp new file mode 100644 index 000000000..3114ef466 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const2.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + const any< ::boost::mpl::vector<copy_constructible<>, typeid_<> > > y(2); + int i = *any_cast<int*>(&y); +} diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_discard_const3.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const3.cpp new file mode 100644 index 000000000..32bd9cf9c --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const3.cpp @@ -0,0 +1,23 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i = 2; + any< ::boost::mpl::vector<copy_constructible<>, typeid_<> >, const _self&> y(i); + int j = any_cast<int&>(y); +} diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_discard_const4.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const4.cpp new file mode 100644 index 000000000..5a1f89ef6 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const4.cpp @@ -0,0 +1,23 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i = 2; + const any< ::boost::mpl::vector<copy_constructible<>, typeid_<> >, const _self&> y(i); + int j = any_cast<int&>(y); +} diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_discard_const5.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const5.cpp new file mode 100644 index 000000000..486e1449a --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const5.cpp @@ -0,0 +1,23 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i = 2; + any< ::boost::mpl::vector<copy_constructible<>, typeid_<> >, const _self&> y(i); + int j = *any_cast<int*>(&y); +} diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_discard_const6.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const6.cpp new file mode 100644 index 000000000..474244795 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_discard_const6.cpp @@ -0,0 +1,23 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i = 2; + const any< ::boost::mpl::vector<copy_constructible<>, typeid_<> >, const _self&> y(i); + int j = *any_cast<int*>(&y); +} diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_pointer_to_ref.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_pointer_to_ref.cpp new file mode 100644 index 000000000..2af8da94f --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_pointer_to_ref.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + any< ::boost::mpl::vector<copy_constructible<>, typeid_<> > > y(2); + int i = any_cast<int&>(&y); +} diff --git a/src/boost/libs/type_erasure/test/fail_any_cast_pointer_to_val.cpp b/src/boost/libs/type_erasure/test/fail_any_cast_pointer_to_val.cpp new file mode 100644 index 000000000..f5dd7cc16 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_any_cast_pointer_to_val.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + any< ::boost::mpl::vector<copy_constructible<>, typeid_<> > > y(2); + int i = any_cast<int>(&y); +} diff --git a/src/boost/libs/type_erasure/test/fail_binding_convert_no_mapping.cpp b/src/boost/libs/type_erasure/test/fail_binding_convert_no_mapping.cpp new file mode 100644 index 000000000..88d70b6e8 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_binding_convert_no_mapping.cpp @@ -0,0 +1,25 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/binding.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/static_binding.hpp> +#include <boost/mpl/map.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/pair.hpp> + +using namespace boost::type_erasure; + +int main() +{ + binding< boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b1( + make_binding<boost::mpl::map<boost::mpl::pair<_a, int>, boost::mpl::pair<_b, int> > >()); + binding< typeid_<_a> > b2(b1, make_binding<boost::mpl::map<> >()); +} diff --git a/src/boost/libs/type_erasure/test/fail_construct_mismatch.cpp b/src/boost/libs/type_erasure/test/fail_construct_mismatch.cpp new file mode 100644 index 000000000..847e38380 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_construct_mismatch.cpp @@ -0,0 +1,21 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/map.hpp> + +using namespace boost::type_erasure; +namespace mpl = boost::mpl; + +int main() +{ + any<copy_constructible<> > x(1, make_binding<mpl::map<mpl::pair<_self, char> > >()); +} diff --git a/src/boost/libs/type_erasure/test/fail_construct_mismatch_cref.cpp b/src/boost/libs/type_erasure/test/fail_construct_mismatch_cref.cpp new file mode 100644 index 000000000..bda7343e8 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_construct_mismatch_cref.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/map.hpp> + +using namespace boost::type_erasure; +namespace mpl = boost::mpl; + +int main() +{ + int i; + any<copy_constructible<>, _self&> x(i, make_binding<mpl::map<mpl::pair<_self, char> > >()); +} diff --git a/src/boost/libs/type_erasure/test/fail_construct_mismatch_ref.cpp b/src/boost/libs/type_erasure/test/fail_construct_mismatch_ref.cpp new file mode 100644 index 000000000..bda7343e8 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_construct_mismatch_ref.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/map.hpp> + +using namespace boost::type_erasure; +namespace mpl = boost::mpl; + +int main() +{ + int i; + any<copy_constructible<>, _self&> x(i, make_binding<mpl::map<mpl::pair<_self, char> > >()); +} diff --git a/src/boost/libs/type_erasure/test/fail_construct_mismatch_rref.cpp b/src/boost/libs/type_erasure/test/fail_construct_mismatch_rref.cpp new file mode 100644 index 000000000..fa80fde40 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_construct_mismatch_rref.cpp @@ -0,0 +1,25 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/map.hpp> + +using namespace boost::type_erasure; +namespace mpl = boost::mpl; + +int main() +{ +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + any<copy_constructible<>, _self&&> x(1, make_binding<mpl::map<mpl::pair<_self, char> > >()); +#else +# error "No support for rvalue-reference is enabled. ==> Test fails (as expected) by default!" +#endif +} diff --git a/src/boost/libs/type_erasure/test/fail_cref_assign.cpp b/src/boost/libs/type_erasure/test/fail_cref_assign.cpp new file mode 100644 index 000000000..92898c909 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_cref_assign.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i; + any<typeid_<>, const _self&> x(i); + x = x; +} diff --git a/src/boost/libs/type_erasure/test/fail_default_construct.cpp b/src/boost/libs/type_erasure/test/fail_default_construct.cpp new file mode 100644 index 000000000..8fff301ed --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_default_construct.cpp @@ -0,0 +1,19 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> + +using namespace boost::type_erasure; + +int main() +{ + any<copy_constructible<> > y; +} diff --git a/src/boost/libs/type_erasure/test/fail_increment_discard_const.cpp b/src/boost/libs/type_erasure/test/fail_increment_discard_const.cpp new file mode 100644 index 000000000..367967a79 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_increment_discard_const.cpp @@ -0,0 +1,21 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/operators.hpp> + +using namespace boost::type_erasure; + +int main() +{ + const int i = 0; + any<incrementable<>, const _self&> x(i); + ++x; +} diff --git a/src/boost/libs/type_erasure/test/fail_not_incrementable.cpp b/src/boost/libs/type_erasure/test/fail_not_incrementable.cpp new file mode 100644 index 000000000..6693e1843 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_not_incrementable.cpp @@ -0,0 +1,27 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +class X {}; + +typedef boost::mpl::vector<copy_constructible<>, incrementable<> > test_concept; + +int main() +{ + X x = {}; + any<test_concept> a(x); + ++a; +} diff --git a/src/boost/libs/type_erasure/test/fail_ref_assign.cpp b/src/boost/libs/type_erasure/test/fail_ref_assign.cpp new file mode 100644 index 000000000..55fae3339 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_ref_assign.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i; + any<typeid_<>, _self&> x(i); + x = x; +} diff --git a/src/boost/libs/type_erasure/test/fail_ref_discard_const.cpp b/src/boost/libs/type_erasure/test/fail_ref_discard_const.cpp new file mode 100644 index 000000000..336856cf2 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_ref_discard_const.cpp @@ -0,0 +1,21 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + const any<copy_constructible<> > x(1); + any<copy_constructible<>, _self&> y(x); +} diff --git a/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert.cpp b/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert.cpp new file mode 100644 index 000000000..f136a0f21 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert.cpp @@ -0,0 +1,21 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + const any<boost::mpl::vector<copy_constructible<>, typeid_<> > > x(1); + any<copy_constructible<>, _self&> y(x); +} diff --git a/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert_cref.cpp b/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert_cref.cpp new file mode 100644 index 000000000..171df660d --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert_cref.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i = 1; + const any<boost::mpl::vector<copy_constructible<>, typeid_<> >, const _self&> x(i); + any<copy_constructible<>, _self&> y(x); +} diff --git a/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert_ref.cpp b/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert_ref.cpp new file mode 100644 index 000000000..44c689ebd --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_ref_discard_const_convert_ref.cpp @@ -0,0 +1,22 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + int i = 1; + any<boost::mpl::vector<copy_constructible<>, typeid_<> >, const _self&> x(i); + any<copy_constructible<>, _self&> y(x); +} diff --git a/src/boost/libs/type_erasure/test/fail_ref_discard_const_init.cpp b/src/boost/libs/type_erasure/test/fail_ref_discard_const_init.cpp new file mode 100644 index 000000000..b190b47dc --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_ref_discard_const_init.cpp @@ -0,0 +1,21 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ + const int i = 1; + any<copy_constructible<>, _self&> y(i); +} diff --git a/src/boost/libs/type_erasure/test/fail_rref_assign.cpp b/src/boost/libs/type_erasure/test/fail_rref_assign.cpp new file mode 100644 index 000000000..7103d8b76 --- /dev/null +++ b/src/boost/libs/type_erasure/test/fail_rref_assign.cpp @@ -0,0 +1,26 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +using namespace boost::type_erasure; + +int main() +{ +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + int i; + any<typeid_<>, _self&&> x(std::move(i)); + x = x; +#else +# error "No support for rvalue-reference is enabled. ==> Test fails (as expected) by default!" +#endif +} diff --git a/src/boost/libs/type_erasure/test/test_add.cpp b/src/boost/libs/type_erasure/test/test_add.cpp new file mode 100644 index 000000000..3a1dc9c61 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_add.cpp @@ -0,0 +1,118 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + destructible<T>, + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_same) +{ + typedef ::boost::mpl::vector<common<>, addable<> > test_concept; + any<test_concept> x(1); + any<test_concept> y(2); + any<test_concept> z(x + y); + int i = any_cast<int>(z); + BOOST_CHECK_EQUAL(i, 3); +} + +BOOST_AUTO_TEST_CASE(test_int1) +{ + typedef ::boost::mpl::vector<common<>, addable<_self, int> > test_concept; + any<test_concept> x(1); + any<test_concept> z(x + 2); + int i = any_cast<int>(z); + BOOST_CHECK_EQUAL(i, 3); +} + +BOOST_AUTO_TEST_CASE(test_int2) +{ + typedef ::boost::mpl::vector<common<>, addable<int, _self, _self> > test_concept; + any<test_concept> x(1); + any<test_concept> z(2 + x); + int i = any_cast<int>(z); + BOOST_CHECK_EQUAL(i, 3); +} + +BOOST_AUTO_TEST_CASE(test_mixed) +{ + typedef ::boost::mpl::vector<common<_a>, common<_b>, addable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> x(1.0, 2); + any<test_concept, _a> z(get<0>(x) + get<1>(x)); + double d = any_cast<double>(z); + BOOST_CHECK_EQUAL(d, 3); +} + +BOOST_AUTO_TEST_CASE(test_overload) +{ + typedef ::boost::mpl::vector< + common<_a>, + common<_b>, + addable<_a>, + addable<_a, int>, + addable<int, _a, _a>, + addable<_b>, + addable<_b, int>, + addable<int, _b, _b>, + addable<_a, _b> + > test_concept; + tuple<test_concept, _a, _b> t(1.0, 2); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + { + any<test_concept, _a> z(x + x); + BOOST_CHECK_EQUAL(any_cast<double>(z), 2.0); + } + + { + any<test_concept, _a> z(x + 3); + BOOST_CHECK_EQUAL(any_cast<double>(z), 4.0); + } + + { + any<test_concept, _a> z(3 + x); + BOOST_CHECK_EQUAL(any_cast<double>(z), 4.0); + } + + { + any<test_concept, _b> z(y + y); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + } + + { + any<test_concept, _b> z(y + 3); + BOOST_CHECK_EQUAL(any_cast<int>(z), 5); + } + + { + any<test_concept, _b> z(3 + y); + BOOST_CHECK_EQUAL(any_cast<int>(z), 5); + } + + { + any<test_concept, _a> z(x + y); + BOOST_CHECK_EQUAL(any_cast<double>(z), 3); + } +} diff --git a/src/boost/libs/type_erasure/test/test_add_assign.cpp b/src/boost/libs/type_erasure/test/test_add_assign.cpp new file mode 100644 index 000000000..5ea0b31b8 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_add_assign.cpp @@ -0,0 +1,140 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + destructible<T>, + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_same) +{ + typedef ::boost::mpl::vector<common<>, add_assignable<> > test_concept; + any<test_concept> x(1); + any<test_concept> y(2); + any<test_concept>& z(x += y); + BOOST_CHECK_EQUAL(any_cast<int>(x), 3); + BOOST_CHECK_EQUAL(&x, &z); +} + +BOOST_AUTO_TEST_CASE(test_int1) +{ + typedef ::boost::mpl::vector<common<>, add_assignable<_self, int> > test_concept; + any<test_concept> x(1); + any<test_concept>& z(x += 2); + BOOST_CHECK_EQUAL(any_cast<int>(x), 3); + BOOST_CHECK_EQUAL(&x, &z); +} + +BOOST_AUTO_TEST_CASE(test_int2) +{ + typedef ::boost::mpl::vector<common<>, add_assignable<int, _self> > test_concept; + int x = 1; + any<test_concept> y(2); + int& z(x += y); + BOOST_CHECK_EQUAL(x, 3); + BOOST_CHECK_EQUAL(&x, &z); +} + +BOOST_AUTO_TEST_CASE(test_mixed) +{ + typedef ::boost::mpl::vector<common<_a>, common<_b>, add_assignable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> t(1.0, 2); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + any<test_concept, _a>& z(x += y); + BOOST_CHECK_EQUAL(any_cast<double>(x), 3.0); + BOOST_CHECK_EQUAL(&x, &z); +} + +BOOST_AUTO_TEST_CASE(test_overload) +{ + typedef ::boost::mpl::vector< + common<_a>, + common<_b>, + add_assignable<_a>, + add_assignable<_a, int>, + add_assignable<double, _a>, + add_assignable<_b>, + add_assignable<_b, int>, + add_assignable<double, _b>, + add_assignable<_a, _b> + > test_concept; + tuple<test_concept, _a, _b> t(1.0, 2); + + { + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _a> y(get<0>(t)); + any<test_concept, _a>& z(x += y); + BOOST_CHECK_EQUAL(any_cast<double>(x), 2.0); + BOOST_CHECK_EQUAL(&x, &z); + } + + { + any<test_concept, _a> x(get<0>(t)); + int y = 5; + any<test_concept, _a>& z(x += y); + BOOST_CHECK_EQUAL(any_cast<double>(x), 6.0); + BOOST_CHECK_EQUAL(&x, &z); + } + + { + double x = 11; + any<test_concept, _a> y(get<0>(t)); + double& z(x += y); + BOOST_CHECK_EQUAL(x, 12); + BOOST_CHECK_EQUAL(&x, &z); + } + + { + any<test_concept, _b> x(get<1>(t)); + any<test_concept, _b> y(get<1>(t)); + any<test_concept, _b>& z(x += y); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + BOOST_CHECK_EQUAL(&x, &z); + } + + { + any<test_concept, _b> x(get<1>(t)); + int y = 5; + any<test_concept, _b>& z(x += y); + BOOST_CHECK_EQUAL(any_cast<int>(x), 7); + BOOST_CHECK_EQUAL(&x, &z); + } + + { + double x = 11; + any<test_concept, _b> y(get<1>(t)); + double& z(x += y); + BOOST_CHECK_EQUAL(x, 13); + BOOST_CHECK_EQUAL(&x, &z); + } + + { + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + any<test_concept, _a>& z(x += y); + BOOST_CHECK_EQUAL(any_cast<double>(x), 3.0); + BOOST_CHECK_EQUAL(&x, &z); + } +} diff --git a/src/boost/libs/type_erasure/test/test_any_cast.cpp b/src/boost/libs/type_erasure/test/test_any_cast.cpp new file mode 100644 index 000000000..c38428654 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_any_cast.cpp @@ -0,0 +1,168 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_value_to_value) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + any<test_concept> x(2); + BOOST_CHECK_EQUAL(any_cast<int>(x), 2); + BOOST_CHECK_THROW(any_cast<double>(x), bad_any_cast); + const any<test_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); + BOOST_CHECK_THROW(any_cast<double>(y), bad_any_cast); +} + +BOOST_AUTO_TEST_CASE(test_value_to_ref) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + any<test_concept> x(2); + BOOST_CHECK_EQUAL(any_cast<int&>(x), 2); + BOOST_CHECK_EQUAL(any_cast<const int&>(x), 2); + BOOST_CHECK_THROW(any_cast<double&>(x), bad_any_cast); + BOOST_CHECK_THROW(any_cast<const double&>(x), bad_any_cast); + const any<test_concept> y(x); + // BOOST_CHECK_EQUAL(any_cast<int&>(y), 2); + BOOST_CHECK_EQUAL(any_cast<const int&>(y), 2); + // BOOST_CHECK_THROW(any_cast<double&>(y), bad_any_cast); + BOOST_CHECK_THROW(any_cast<const double&>(y), bad_any_cast); +} + +BOOST_AUTO_TEST_CASE(test_value_to_pointer) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + any<test_concept> x(2); + BOOST_CHECK_EQUAL(*any_cast<int*>(&x), 2); + BOOST_CHECK_EQUAL(*any_cast<const int*>(&x), 2); + BOOST_CHECK_EQUAL(any_cast<void*>(&x), any_cast<int*>(&x)); + BOOST_CHECK_EQUAL(any_cast<const void*>(&x), any_cast<const int*>(&x)); + BOOST_CHECK_EQUAL(any_cast<double*>(&x), (double*)0); + BOOST_CHECK_EQUAL(any_cast<const double*>(&x), (double*)0); + const any<test_concept> y(x); + // BOOST_CHECK_EQUAL(*any_cast<int*>(&y), 2); + BOOST_CHECK_EQUAL(*any_cast<const int*>(&y), 2); + // BOOST_CHECK_EQUAL(any_cast<void*>(&y), any_cast<int*>(&y)); + BOOST_CHECK_EQUAL(any_cast<const void*>(&y), any_cast<const int*>(&y)); + // BOOST_CHECK_EQUAL(any_cast<double*>(&y), (double*)0); + BOOST_CHECK_EQUAL(any_cast<const double*>(&y), (double*)0); +} + +BOOST_AUTO_TEST_CASE(test_ref_to_value) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 2; + any<test_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 2); + BOOST_CHECK_THROW(any_cast<double>(x), bad_any_cast); + const any<test_concept, _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); + BOOST_CHECK_THROW(any_cast<double>(y), bad_any_cast); +} + +BOOST_AUTO_TEST_CASE(test_ref_to_ref) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 2; + any<test_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int&>(x), 2); + BOOST_CHECK_EQUAL(any_cast<const int&>(x), 2); + BOOST_CHECK_THROW(any_cast<double&>(x), bad_any_cast); + BOOST_CHECK_THROW(any_cast<const double&>(x), bad_any_cast); + const any<test_concept, _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<int&>(y), 2); + BOOST_CHECK_EQUAL(any_cast<const int&>(y), 2); + BOOST_CHECK_THROW(any_cast<double&>(y), bad_any_cast); + BOOST_CHECK_THROW(any_cast<const double&>(y), bad_any_cast); +} + +BOOST_AUTO_TEST_CASE(test_ref_to_pointer) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 2; + any<test_concept, _self&> x(i); + BOOST_CHECK_EQUAL(*any_cast<int*>(&x), 2); + BOOST_CHECK_EQUAL(*any_cast<const int*>(&x), 2); + BOOST_CHECK_EQUAL(any_cast<void*>(&x), any_cast<int*>(&x)); + BOOST_CHECK_EQUAL(any_cast<const void*>(&x), any_cast<const int*>(&x)); + BOOST_CHECK_EQUAL(any_cast<double*>(&x), (double*)0); + BOOST_CHECK_EQUAL(any_cast<const double*>(&x), (double*)0); + const any<test_concept, _self&> y(x); + BOOST_CHECK_EQUAL(*any_cast<int*>(&y), 2); + BOOST_CHECK_EQUAL(*any_cast<const int*>(&y), 2); + BOOST_CHECK_EQUAL(any_cast<void*>(&y), any_cast<int*>(&y)); + BOOST_CHECK_EQUAL(any_cast<const void*>(&y), any_cast<const int*>(&y)); + BOOST_CHECK_EQUAL(any_cast<double*>(&y), (double*)0); + BOOST_CHECK_EQUAL(any_cast<const double*>(&y), (double*)0); +} + +BOOST_AUTO_TEST_CASE(test_cref_to_value) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 2; + any<test_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 2); + BOOST_CHECK_THROW(any_cast<double>(x), bad_any_cast); + const any<test_concept, const _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); + BOOST_CHECK_THROW(any_cast<double>(y), bad_any_cast); +} + +BOOST_AUTO_TEST_CASE(test_cref_to_ref) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 2; + any<test_concept, const _self&> x(i); + // BOOST_CHECK_EQUAL(any_cast<int&>(x), 2); + BOOST_CHECK_EQUAL(any_cast<const int&>(x), 2); + // BOOST_CHECK_THROW(any_cast<double&>(x), bad_any_cast); + BOOST_CHECK_THROW(any_cast<const double&>(x), bad_any_cast); + const any<test_concept, const _self&> y(x); + // BOOST_CHECK_EQUAL(any_cast<int&>(y), 2); + BOOST_CHECK_EQUAL(any_cast<const int&>(y), 2); + // BOOST_CHECK_THROW(any_cast<double&>(y), bad_any_cast); + BOOST_CHECK_THROW(any_cast<const double&>(y), bad_any_cast); +} + +BOOST_AUTO_TEST_CASE(test_cref_to_pointer) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 2; + any<test_concept, const _self&> x(i); + // BOOST_CHECK_EQUAL(*any_cast<int*>(&x), 2); + BOOST_CHECK_EQUAL(*any_cast<const int*>(&x), 2); + // BOOST_CHECK_EQUAL(any_cast<void*>(&x), any_cast<int*>(&x)); + BOOST_CHECK_EQUAL(any_cast<const void*>(&x), any_cast<const int*>(&x)); + // BOOST_CHECK_EQUAL(any_cast<double*>(&x), (double*)0); + BOOST_CHECK_EQUAL(any_cast<const double*>(&x), (double*)0); + const any<test_concept, const _self&> y(x); + // BOOST_CHECK_EQUAL(*any_cast<int*>(&y), 2); + BOOST_CHECK_EQUAL(*any_cast<const int*>(&y), 2); + // BOOST_CHECK_EQUAL(any_cast<void*>(&y), any_cast<int*>(&y)); + BOOST_CHECK_EQUAL(any_cast<const void*>(&y), any_cast<const int*>(&y)); + // BOOST_CHECK_EQUAL(any_cast<double*>(&y), (double*)0); + BOOST_CHECK_EQUAL(any_cast<const double*>(&y), (double*)0); +} diff --git a/src/boost/libs/type_erasure/test/test_assign.cpp b/src/boost/libs/type_erasure/test/test_assign.cpp new file mode 100644 index 000000000..7e68a505a --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_assign.cpp @@ -0,0 +1,2381 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/config.hpp> + +#ifdef BOOST_MSVC +#pragma warning(disable:4244) // conversion from double to int +#endif + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/relaxed.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; +using boost::core::demangle; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template<class T = _self> +struct movable_common : ::boost::mpl::vector< + destructible<T>, + constructible<T(T&&)>, + typeid_<T> +> {}; + +template<class T = _self, class U = T> +struct move_assignable : ::boost::mpl::vector< + assignable<T, U&&> +> {}; + +#endif + +template<class T, bool CCtor, bool MoveCtor, bool CAssign, bool MoveAssign> +struct test_class +{ + explicit test_class(T n) : value(n) {} + test_class(const test_class& src) : value(src.value) + { + BOOST_STATIC_ASSERT_MSG(CCtor, "Copy constructor not allowed."); + } + test_class& operator=(const test_class& src) + { + BOOST_STATIC_ASSERT_MSG(CAssign, "Copy assignment not allowed."); + value = src.value; + return *this; + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + test_class(test_class&& src) : value(src.value) + { + BOOST_STATIC_ASSERT_MSG(MoveCtor, "Move constructor not allowed."); + src.value = 0; + } + test_class& operator=(test_class&& src) + { + BOOST_STATIC_ASSERT_MSG(MoveAssign, "Move assignment not allowed."); + value = src.value; + src.value = 0; + return *this; + } +#endif + bool operator==(T n) const { return value == n; } + T value; +}; + +template<class T, bool CCtor, bool MoveCtor, bool CAssign, bool MoveAssign> +std::ostream& operator<<(std::ostream& os, const test_class<T, CCtor, MoveCtor, CAssign, MoveAssign>& t) +{ + return os << t.value; +} + +enum copy_info { + id_lvalue = 1, + id_const_lvalue = 2, +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + id_rvalue = 3, + id_maybe_const_lvalue = id_lvalue, // used for the id of construction from a raw value +#else + id_rvalue = id_const_lvalue, + id_maybe_const_lvalue = id_const_lvalue, +#endif + id_construct = 4, + id_assign = 8, + id_copy = 16, + id_int = 32 +}; + +#ifdef BOOST_MSVC +#pragma warning(disable:4521) // multiple copy constructors specified +#pragma warning(disable:4522) // multiple assignment operators specified +#endif + +template<class T> +struct copy_tracker +{ + copy_tracker(const copy_tracker& src) : value(src.value), info(id_const_lvalue | id_construct | id_copy), moved_from(false) {} + copy_tracker(copy_tracker& src) : value(src.value), info(id_lvalue | id_construct | id_copy), moved_from(false) {} + copy_tracker& operator=(const copy_tracker& src) { value = (src.value); info = (id_const_lvalue | id_assign | id_copy); moved_from = false; return *this; } + copy_tracker& operator=(copy_tracker& src) { value = (src.value); info = (id_lvalue | id_assign | id_copy); moved_from = false; return *this; } + copy_tracker(const T& src) : value(src), info(id_const_lvalue | id_construct | id_int), moved_from(false) {} + copy_tracker(T& src) : value(src), info(id_lvalue | id_construct | id_int), moved_from(false) {} + copy_tracker& operator=(const T& src) { value = (src); info = (id_const_lvalue | id_assign | id_int); moved_from = false; return *this; } + copy_tracker& operator=(T& src) { value = (src); info = (id_lvalue | id_assign | id_int); moved_from = false; return *this; } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + copy_tracker(copy_tracker&& src) : value(std::move(src.value)), info(id_rvalue | id_construct | id_copy), moved_from(false) { src.moved_from = true; } + copy_tracker& operator=(copy_tracker&& src) { value = std::move(src.value); info = (id_rvalue | id_assign | id_copy); moved_from = false; src.moved_from = true; return *this; } + copy_tracker(T&& src) : value(std::move(src)), info(id_rvalue | id_construct | id_int), moved_from(false) {} + copy_tracker& operator=(T&& src) { value = std::move(src); info = (id_rvalue | id_assign | id_int); moved_from = false; return *this; } +#endif + template<class U> + explicit copy_tracker(const U& src) : value(src), info(id_const_lvalue | id_construct | id_int), moved_from(false) {} + T value; + int info; + bool moved_from; +}; + +template<class T> +struct value_holder +{ + typedef copy_tracker<T> type; + typedef copy_tracker<T> unwrapped_type; + template<class U> + value_holder(const U& u) : value(u) {} + type value; + type get() { return value; } + const unwrapped_type& unwrap() { return value; } + template<class U> + const U& unwrap() { return value; } +}; + +template<class C, class P> +struct value_holder<any<C, P> > +{ + typedef any<C, P> type; + typedef any<C, P> unwrapped_type; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<class U> + value_holder(U&& u) : value(std::forward<U>(u)) {} +#else + template<class U> + value_holder(U& u) : value(u) {} + template<class U> + value_holder(const U& u) : value(u) {} +#endif + type value; + type get() { return value; } + const unwrapped_type& unwrap() { return value; } + template<class U> + const U& unwrap() { return any_cast<const U&>(value); } +}; + +template<class T> +struct value_holder<T&> +{ + typedef typename value_holder<T>::type& type; + typedef typename value_holder<T>::unwrapped_type unwrapped_type; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<class U> + value_holder(U&& u) : impl(std::forward<U>(u)) {} +#else + template<class U> + value_holder(U& u) : impl(u) {} + template<class U> + value_holder(const U& u) : impl(u) {} +#endif + value_holder<T> impl; + type get() { return impl.value; } + const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } + template<class U> + const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } +}; + +template<class T> +struct value_holder<const T&> +{ + typedef const typename value_holder<T>::type& type; + typedef typename value_holder<T>::unwrapped_type unwrapped_type; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<class U> + value_holder(U&& u) : impl(std::forward<U>(u)) {} +#else + template<class U> + value_holder(U& u) : impl(u) {} + template<class U> + value_holder(const U& u) : impl(u) {} +#endif + value_holder<T> impl; + type get() { return impl.value; } + const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } + template<class U> + const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template<class T> +struct value_holder<T&&> +{ + typedef typename value_holder<T>::type&& type; + typedef typename value_holder<T>::unwrapped_type unwrapped_type; + template<class U> + value_holder(U&& u) : impl(std::forward<U>(u)) {} + value_holder<T> impl; + type get() { return std::move(impl.value); } + const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } + template<class U> + const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } +}; + +#endif + +template<class T, class A> +struct value_holder<T(A)> +{ +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<class U> + value_holder(U&& u) : init(std::forward<U>(u)), impl(init.get()) {} +#else + template<class U> + value_holder(U& u) : init(u), impl(init.get()) {} + template<class U> + value_holder(const U& u) : init(u), impl(init.get()) {} +#endif + value_holder<A> init; + value_holder<T> impl; + typedef typename value_holder<T>::type type; + typedef typename value_holder<A>::unwrapped_type unwrapped_type; + type get() { return impl.get(); } + const unwrapped_type& unwrap() { return unwrap<unwrapped_type>(); } + template<class U> + const U& unwrap() { return impl.template unwrap<unwrapped_type>(); } +}; + +#define TEST_ASSIGNMENT_I(LHS, RHS, result, ptr_op, R) \ + try \ + { \ + value_holder<LHS> lhs(17); \ + value_holder<RHS> rhs(23); \ + const void * original = any_cast<const void*>(&lhs.get()); \ + lhs.get() = rhs.get(); \ + typedef value_holder<R>::unwrapped_type expected_type; \ + if(const expected_type* ptr = \ + any_cast<const expected_type*>(&lhs.get())) \ + { \ + BOOST_TEST(ptr->value == 23); \ + BOOST_TEST(ptr->info == (result)); \ + BOOST_TEST(ptr ptr_op original); \ + } \ + else \ + { \ + BOOST_ERROR("Wrong type: Expected " \ + << boost::core::demangle(typeid(expected_type).name()) \ + << " but got " \ + << boost::core::demangle(typeid_of(lhs.get()).name())); \ + } \ + } \ + catch(bad_function_call&) \ + { \ + BOOST_ERROR("bad_function_call in " \ + << demangle(typeid(value_holder<LHS>::type).name()) \ + << " = " \ + << demangle(typeid(value_holder<RHS>::type).name())); \ + } + +#define TEST_ASSIGNMENT_id_dispatch(LHS, RHS, result) \ + TEST_ASSIGNMENT_I(LHS, RHS, result, ==, LHS) + +#define TEST_ASSIGNMENT_id_fallback(LHS, RHS, result) \ + TEST_ASSIGNMENT_I(LHS, RHS, result, !=, RHS) + +#define TEST_ASSIGNMENT_id_throw(LHS, RHS, result) \ + { \ + value_holder<LHS> lhs(17); \ + value_holder<RHS> rhs(23); \ + BOOST_CHECK_THROW(lhs.get() = rhs.get(), bad_function_call); \ + } + +#define TEST_ASSIGNMENT(LHS, RHS, tag, result) \ + BOOST_PP_CAT(TEST_ASSIGNMENT_, tag)(LHS, RHS, result) + +BOOST_AUTO_TEST_CASE(test_nothing) +{ + // Nothing to test. Assignment is entirely illegal +} + +BOOST_AUTO_TEST_CASE(test_nothing_relaxed) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + constructible<_self(int)>, + relaxed + > test_concept; + typedef test_class<int, false, false, false, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + + // Compile-time check. + binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >(); + any_val v1(test_binding, 1); + + // assignment of same type + + // different stored type + + // raw value + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with a different type + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + + // assignment to an rvalue reference + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +#endif +} + +BOOST_AUTO_TEST_CASE(test_copy_assignable) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + assignable<>, + constructible<_self(int)> + > test_concept; + typedef test_class<int, false, false, true, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >(); + any_val v1(test_binding, 1); + + // assignment of same type +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); +#endif + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type (undefined behavior) + + // raw value (compile error) + + // assignment to a reference +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); +#endif + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type (undefined behavior) + + // reference with raw value (compile error) + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // rvalue reference with a different type (undefined behavior) + + // rvalue reference with raw value (compile error) +#endif +} + +BOOST_AUTO_TEST_CASE(test_copy_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + assignable<>, + constructible<_self(int)>, + relaxed + > test_concept; + typedef test_class<int, false, false, true, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >(); + any_val v1(test_binding, 1); + + // assignment of same type +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); +#endif + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_ASSIGNMENT(any_val&(int), any_val&&(long), id_throw, 0); +#endif + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_throw, 0); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment to a reference +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); +#endif + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(long), id_throw, 0); +#endif + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_throw, ); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +#endif +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +BOOST_AUTO_TEST_CASE(test_move_assignable) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + move_assignable<>, + constructible<_self(int)> + > test_concept; + typedef test_class<int, false, false, false, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + + // Compile-time check. + binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >(); + any_val v1(test_binding, 1); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + + // different stored type + + // raw value + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + + // reference with a different type + + // reference with raw value + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);; + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type + + // rvalue reference with raw value +} + +BOOST_AUTO_TEST_CASE(test_move_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + move_assignable<>, + constructible<_self(int)>, + relaxed + > test_concept; + typedef test_class<int, false, false, false, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + + // Compile-time check. + binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >(); + any_val v1(test_binding, 1); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val&&(long), id_throw, 0); + + // raw value + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with a different type + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +} + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + +BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + assignable<>, + move_assignable<>, + constructible<_self(int)> + > test_concept; + typedef test_class<int, false, false, true, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >(); + any_val v1(test_binding, 1); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type (undefined behavior) + + // raw value (compile error) + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type (undefined behavior) + + // reference with raw value (compile error) + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type (undefined behavior) + + // rvalue reference with raw value (compile error) +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + assignable<>, + move_assignable<>, + constructible<_self(int)>, + relaxed + > test_concept; + typedef test_class<int, false, false, true, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + binding<test_concept> test_binding = make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > >(); + any_val v1(test_binding, 1); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val&&(long), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_throw, 0); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type + TEST_ASSIGNMENT(any_ref&(int&), any_val&&(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +} + +#endif // BOOST_NO_CXX11_REF_QUALIFIERS + +#endif // BOOST_NO_CXX11_RVALUE_REFERENCES + +BOOST_AUTO_TEST_CASE(test_copy_constructible_only) +{ + // Nothing to test. Assignment is entirely illegal +} + +BOOST_AUTO_TEST_CASE(test_copy_constructible_only_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + relaxed + > test_concept; + typedef test_class<int, true, false, false, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with a different type + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment to an rvalue reference + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(int), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +#endif +} + +BOOST_AUTO_TEST_CASE(test_copy) +{ + typedef ::boost::mpl::vector< + common<>, + assignable<> + > test_concept; + typedef test_class<int, true, false, true, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type (undefined behavior) + + // raw value (compile error) + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type (undefined behavior) + + // reference with raw value (compile error) + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // rvalue reference with a different type (undefined behavior) + + // rvalue reference with raw value (compile error) +#endif +} + +BOOST_AUTO_TEST_CASE(test_copy_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + assignable<>, + relaxed + > test_concept; + typedef test_class<int, true, false, true, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_maybe_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type + TEST_ASSIGNMENT(any_ref&(int&), any_val(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +#endif +} + + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +BOOST_AUTO_TEST_CASE(test_copy_constructable_move_assignable) +{ + typedef ::boost::mpl::vector< + common<>, + move_assignable<> + > test_concept; + typedef test_class<int, true, false, false, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type const&), id_dispatch, id_rvalue | id_assign | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + + // different stored type + + // raw value + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + + // reference with a different type + + // reference with raw value + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy);; + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type + + // rvalue reference with raw value +} + +BOOST_AUTO_TEST_CASE(test_copy_constructable_move_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + move_assignable<>, + relaxed + > test_concept; + typedef test_class<int, true, false, false, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with a different type + TEST_ASSIGNMENT(any_ref&(int&), any_val(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +} + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + +BOOST_AUTO_TEST_CASE(test_copy_constructible_move_and_copy_assignable) +{ + typedef ::boost::mpl::vector< + common<>, + assignable<>, + move_assignable<> + > test_concept; + typedef test_class<int, true, false, true, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type (undefined behavior) + + // raw value (compile error) + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type (undefined behavior) + + // reference with raw value (compile error) + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type (undefined behavior) + + // rvalue reference with raw value (compile error) +} + +BOOST_AUTO_TEST_CASE(test_copy_constructible_move_and_copy_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + assignable<>, + move_assignable<>, + relaxed + > test_concept; + typedef test_class<int, true, false, true, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment to a reference + TEST_ASSIGNMENT(any_ref&(int&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // reference with a different type + TEST_ASSIGNMENT(any_ref&(int&), any_val(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_val&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_cref const&(long&), id_throw, 0); + + // reference with raw value + TEST_ASSIGNMENT(any_ref&(int&), int&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_ref&(int&), long&, id_fallback, id_const_lvalue | id_construct | id_int); + + typedef any<test_concept, _self&&> any_rref; + + // rvalue reference as the rhs + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), any_rref(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref&(long&&), id_throw, 0); + TEST_ASSIGNMENT(any_ref&(int&), any_rref const&(long&&), id_throw, 0); + + // assignment to an rvalue reference (same dispatching behavior as lvalue reference) + TEST_ASSIGNMENT(any_rref&(int&&), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // rvalue reference with a different type + TEST_ASSIGNMENT(any_rref&(int&&), any_val&&(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), any_val&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_val const&(long), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_ref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_cref const&(long&), id_throw, 0); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), any_rref const&(long&&), id_fallback, id_const_lvalue | id_construct | id_int); + + // rvalue reference with raw value + TEST_ASSIGNMENT(any_rref&(int&&), int&&, id_fallback, id_const_lvalue | id_construct | id_int); + TEST_ASSIGNMENT(any_rref&(int&&), long&&, id_fallback, id_const_lvalue | id_construct | id_int); +} + +#endif // BOOST_NO_CXX11_REF_QUALIFIERS + +#endif // BOOST_NO_CXX11_RVALUE_REFERENCES + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_only) +{ + // Nothing to test. Assignment is entirely illegal +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_only_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + movable_common<>, + relaxed + > test_concept; + typedef test_class<int, true, true, false, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + typedef any<test_concept, _self&&> any_rref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_fallback, id_rvalue | id_construct | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_copy_assignable) +{ + typedef ::boost::mpl::vector< + common<>, + movable_common<>, + assignable<> + > test_concept; + typedef test_class<int, true, true, true, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + typedef any<test_concept, _self&&> any_rref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type (undefined behavior) +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_copy_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + movable_common<>, + assignable<>, + relaxed + > test_concept; + typedef test_class<int, true, true, true, false> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + typedef any<test_concept, _self&&> any_rref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructable_move_assignable) +{ + typedef ::boost::mpl::vector< + common<>, + movable_common<>, + move_assignable<> + > test_concept; + typedef test_class<int, true, true, false, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&&> any_rref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val(test_type const&), id_dispatch, id_rvalue | id_assign | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // different stored type + + // raw value +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructable_move_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + movable_common<>, + move_assignable<>, + relaxed + > test_concept; + typedef test_class<int, true, true, false, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + typedef any<test_concept, _self&&> any_rref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_move_and_copy_assignable) +{ + typedef ::boost::mpl::vector< + common<>, + movable_common<>, + assignable<>, + move_assignable<> + > test_concept; + typedef test_class<int, true, true, true, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + typedef any<test_concept, _self&&> any_rref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(test_type&), any_val&(const test_type&), id_dispatch, id_const_lvalue | id_assign | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // different stored type (undefined behavior) +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_constructible_move_and_copy_assignable_relaxed) +{ + typedef ::boost::mpl::vector< + common<>, + movable_common<>, + assignable<>, + move_assignable<>, + relaxed + > test_concept; + typedef test_class<int, true, true, true, true> test_type; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + typedef any<test_concept, const _self&> any_cref; + typedef any<test_concept, _self&&> any_rref; + + // Compile-time check. + TEST_ASSIGNMENT(any_val&(int), test_type, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), test_type const&, id_fallback, id_const_lvalue | id_construct | id_copy); + + // assignment of same type + TEST_ASSIGNMENT(any_val&(int), any_val(int), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(int), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(int&), id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(int&&), id_dispatch, id_rvalue | id_assign | id_copy); + + // different stored type + TEST_ASSIGNMENT(any_val&(int), any_val(long), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_val const&(long), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_ref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_cref const&(long&), id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), any_rref const&(long&&), id_fallback, id_rvalue | id_construct | id_copy); + + // raw value + TEST_ASSIGNMENT(any_val&(int), int, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_fallback, id_const_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long, id_fallback, id_rvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long&, id_fallback, id_lvalue | id_construct | id_copy); + TEST_ASSIGNMENT(any_val&(int), long const&, id_fallback, id_const_lvalue | id_construct | id_copy); +} + +#endif // BOOST_NO_RVALUE_REFERENCES || BOOST_NO_CXX11_REF_QUALIFIERS + +BOOST_AUTO_TEST_CASE(test_basic_int) +{ + typedef ::boost::mpl::vector< + common<>, + assignable<_self, copy_tracker<int> > + > test_concept; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + + TEST_ASSIGNMENT(any_val&(int), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); + + TEST_ASSIGNMENT(any_ref&(int&), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef any<test_concept, _self&&> any_rref; + TEST_ASSIGNMENT(any_rref&(int&&), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); +#endif +} + +BOOST_AUTO_TEST_CASE(test_basic_relaxed_int) +{ + typedef ::boost::mpl::vector< + common<>, + assignable<_self, copy_tracker<int> >, + relaxed + > test_concept; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + + TEST_ASSIGNMENT(any_val&(int), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); + + TEST_ASSIGNMENT(any_ref&(int&), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef any<test_concept, _self&&> any_rref; + TEST_ASSIGNMENT(any_rref&(int&&), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); +#endif +} + +BOOST_AUTO_TEST_CASE(test_relaxed_no_copy_int) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + assignable<_self, copy_tracker<int> >, + relaxed + > test_concept; + + typedef any<test_concept> any_val; + typedef any<test_concept, _self&> any_ref; + + TEST_ASSIGNMENT(any_val&(int), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_val&(int), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); + + TEST_ASSIGNMENT(any_ref&(int&), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_ref&(int&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef any<test_concept, _self&&> any_rref; + TEST_ASSIGNMENT(any_rref&(int&&), int, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), int&, id_dispatch, id_const_lvalue | id_assign | id_copy); + TEST_ASSIGNMENT(any_rref&(int&&), int const&, id_dispatch, id_const_lvalue | id_assign | id_copy); +#endif +} + +BOOST_AUTO_TEST_CASE(test_relaxed_no_assign_int) +{ + typedef ::boost::mpl::vector< + common<>, + relaxed + > test_concept; + any<test_concept> x(1); + x = 2; + BOOST_CHECK_EQUAL(any_cast<int>(x), 2); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +struct move_only_assign_int +{ + explicit move_only_assign_int(int i) + : value(i) {} + move_only_assign_int(move_only_assign_int&& other) + : value(other.value) { other.value = 0; } + move_only_assign_int& operator=(move_only_assign_int&& other) + { value = other.value; other.value = 0; return *this; } + move_only_assign_int& operator=(int&& i) + { value = i; return *this; } + int value; +private: + move_only_assign_int(const move_only_assign_int&); + move_only_assign_int& operator=(const move_only_assign_int&); +}; + +struct only_assign_int +{ + explicit only_assign_int(int i) + : value(i) {} + only_assign_int& operator=(int&& i) + { value = i; return *this; } + int value; +private: + only_assign_int(only_assign_int&&); + only_assign_int(const only_assign_int&); + only_assign_int& operator=(only_assign_int&&); + only_assign_int& operator=(const only_assign_int&); +}; + +struct move_and_copy_assign_int +{ + explicit move_and_copy_assign_int(int i) + : value(i) {} + move_and_copy_assign_int& operator=(move_and_copy_assign_int&& other) + { value = other.value; other = 0; return *this; } + move_and_copy_assign_int& operator=(const move_and_copy_assign_int& other) + { value = other.value; return *this; } + move_and_copy_assign_int& operator=(int&& i) + { value = i; return *this; } + move_and_copy_assign_int& operator=(const int& i) + { value = i; return *this; } + int value; +private: + move_and_copy_assign_int(move_and_copy_assign_int&&); + move_and_copy_assign_int(const move_and_copy_assign_int&); +}; + +struct move_and_copy_construct_assign_int +{ + explicit move_and_copy_construct_assign_int(int i) + : value(i) {} + move_and_copy_construct_assign_int(move_and_copy_construct_assign_int&& other) + : value(other.value) { other.value = 0; } + move_and_copy_construct_assign_int(const move_and_copy_construct_assign_int& other) + : value(other.value) {} + move_and_copy_construct_assign_int& operator=(move_and_copy_construct_assign_int&& other) + { value = other.value; other = 0; return *this; } + move_and_copy_construct_assign_int& operator=(const move_and_copy_construct_assign_int& other) + { value = other.value; return *this; } + move_and_copy_construct_assign_int& operator=(int&& i) + { value = i; return *this; } + move_and_copy_construct_assign_int& operator=(const int& i) + { value = i; return *this; } + int value; +}; + +struct copy_only_assign_int +{ + explicit copy_only_assign_int(int i) + : value(i) {} + copy_only_assign_int(const copy_only_assign_int& other) + : value(other.value) {} + copy_only_assign_int& operator=(const copy_only_assign_int& other) + { value = other.value; return *this; } + copy_only_assign_int& operator=(int&& i) + { value = i; return *this; } + copy_only_assign_int& operator=(const int& i) + { value = i; return *this; } + int value; +private: + copy_only_assign_int(copy_only_assign_int&&); + copy_only_assign_int& operator=(copy_only_assign_int&&); +}; + +struct copy_only_assign_double +{ + explicit copy_only_assign_double(double i) + : value(i) {} + copy_only_assign_double(const copy_only_assign_double& other) + : value(other.value) {} + copy_only_assign_double& operator=(const copy_only_assign_double& other) + { value = other.value; return *this; } + copy_only_assign_double& operator=(double&& i) + { value = i; return *this; } + copy_only_assign_double& operator=(const double& i) + { value = i; return *this; } + double value; +private: + copy_only_assign_double(copy_only_assign_double&&); + copy_only_assign_double& operator=(copy_only_assign_double&&); +}; + +BOOST_AUTO_TEST_CASE(test_movable_basic_int) +{ + typedef ::boost::mpl::vector< + movable_common<>, + move_assignable<_self, int> + > test_concept; + typedef move_only_assign_int test_type; + test_type source_x(1); + + any<test_concept> x(std::move(source_x)); + test_type* ip = any_cast<test_type*>(&x); + x = std::move(2); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2); + // make sure that we're actually using assignment + // of the underlying object, not copy and swap. + BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip); +} + +BOOST_AUTO_TEST_CASE(test_movable_basic_relaxed_int) +{ + typedef ::boost::mpl::vector< + movable_common<>, + move_assignable<_self, int>, + relaxed + > test_concept; + typedef move_only_assign_int test_type; + test_type source_x(1); + + any<test_concept> x(std::move(source_x)); + test_type* ip = any_cast<test_type*>(&x); + x = std::move(2); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2); + // make sure that we're actually using assignment + // of the underlying object, not copy and swap. + BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip); +} + +BOOST_AUTO_TEST_CASE(test_relaxed_no_constructible_int) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + constructible<_self(int)>, + move_assignable<_self, int>, + relaxed + > test_concept; + typedef only_assign_int test_type; + + typedef ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > type; + any<test_concept> x(binding<test_concept>(make_binding<type>()), 1); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 1); + test_type* ip = any_cast<test_type*>(&x); + x = std::move(2); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2); + // make sure that we're actually using assignment + // of the underlying object, not copy and swap. + BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip); +} + +BOOST_AUTO_TEST_CASE(test_movable_relaxed_no_assign_int) +{ + typedef ::boost::mpl::vector< + movable_common<>, + relaxed + > test_concept; + typedef move_only_assign_int test_type; + test_type source_x(1); + + any<test_concept> x(std::move(source_x)); + x = test_type(2); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2); +} + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + +BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable_int) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + constructible<_self(int)>, + assignable<_self, _self>, + move_assignable<_self, _self>, + assignable<_self, int>, + move_assignable<_self, int>, + relaxed + > test_concept; + typedef move_and_copy_assign_int test_type; + typedef ::boost::mpl::map< ::boost::mpl::pair<_self, test_type> > type; + + any<test_concept> x(binding<test_concept>(make_binding<type>()), 1); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 1); + + any<test_concept> y(binding<test_concept>(make_binding<type>()), 2); + x = y; + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2); + + any<test_concept> z(binding<test_concept>(make_binding<type>()), 3); + x = std::move(z); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 3); + + x = 4; + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 4); + + x = std::move(5); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 5); +} + +BOOST_AUTO_TEST_CASE(test_move_and_copy_assignable_copy_construct_int) +{ + typedef ::boost::mpl::vector< + common<>, + assignable<_self, _self>, + move_assignable<_self, _self>, + assignable<_self, int>, + move_assignable<_self, int>, + relaxed + > test_concept; + typedef move_and_copy_construct_assign_int test_type; + test_type source_x(1); + test_type source_y(2); + test_type source_z(3); + + any<test_concept> x(source_x); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 1); + test_type* ip = any_cast<test_type*>(&x); + + any<test_concept> y(source_y); + x = y; + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 2); + // make sure that we're actually using assignment + // of the underlying object, not copy and swap. + BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip); + + any<test_concept> z(source_z); + x = std::move(z); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 3); + // make sure that we're actually using move-assignment + // of the underlying object, not copy and swap. + BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip); + + x = 4; + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 4); + // make sure that we're actually using assignment + // of the underlying object, not copy and swap. + BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip); + + x = std::move(5); + BOOST_CHECK_EQUAL(any_cast<const test_type&>(x).value, 5); + // make sure that we're actually using move-assignment + // of the underlying object, not copy and swap. + BOOST_CHECK_EQUAL(any_cast<test_type*>(&x), ip); +} + +#endif // BOOST_NO_CXX11_REF_QUALIFIERS + +BOOST_AUTO_TEST_CASE(test_assignable_with_conversion) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + assignable<_self, int>, + relaxed + > test_concept; + typedef move_and_copy_construct_assign_int test_type1; + typedef copy_only_assign_int test_type2; + typedef copy_only_assign_double test_type3; + + test_type1 source_x(1); + any<test_concept> x(source_x); + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 1); + + // assigning raw values is supported because "relaxed" is in concept. + test_type2 source_y(2); + x = source_y; + BOOST_CHECK_EQUAL(any_cast<const test_type2&>(x).value, 2); + + // move-assigning raw values is supported because "relaxed" is in concept. + x = test_type1(3); + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 3); + + // assigning int is supported because appropriate "assignable" is in concept. + int int4 = 4; + x = int4; + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 4); + int int5 = 5; + x = std::move(int5); + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 5); + + // assigning double (which is implicitly convertible to int) is supported + // because appropriate "assignable" is in concept. + double double6 = 6.5; + x = double6; // truncates value + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 6); + double double7 = 7.5; + x = std::move(double7); // truncates value + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 7); + + // assigning raw values is supported because "relaxed" is in concept. + test_type3 source_z(8.5); + x = source_z; + BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 8.5); + + // assigning double (which is implicitly convertible to int) is supported + // because appropriate "assignable" is in concept. + double double9 = 9.5; + x = double9; // truncates value + BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 9.0); + double double10 = 10.5; + x = std::move(double10); // truncates value + BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 10.0); +} + +BOOST_AUTO_TEST_CASE(test_move_assignable_with_conversion) +{ + typedef ::boost::mpl::vector< + destructible<>, + typeid_<>, + move_assignable<_self, int>, + relaxed + > test_concept; + typedef move_and_copy_construct_assign_int test_type1; + typedef copy_only_assign_int test_type2; + typedef copy_only_assign_double test_type3; + + test_type1 source_x(1); + any<test_concept> x(source_x); + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 1); + + // assigning raw values is supported because "relaxed" is in concept. + test_type2 source_y(2); + x = source_y; + BOOST_CHECK_EQUAL(any_cast<const test_type2&>(x).value, 2); + + // move-assigning raw values is supported because "relaxed" is in concept. + x = test_type1(3); + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 3); + + // move-assigning int is supported because appropriate "move_assignable" is in concept. + int int4 = 4; + x = std::move(int4); + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 4); + // copy-assigning int is assigning a raw_value. + int int5 = 5; + x = int5; + BOOST_CHECK_EQUAL(any_cast<const int&>(x), 5); + x = source_x; // reset. + + // move-assigning double (which is implicitly convertible to int) is supported + // because appropriate "move_assignable" is in concept. + double double6 = 6.5; + x = std::move(double6); // truncates value + BOOST_CHECK_EQUAL(any_cast<const test_type1&>(x).value, 6); + + // assigning raw values is supported because "relaxed" is in concept. + test_type3 source_z(8.5); + x = source_z; + BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 8.5); + + // move-assigning double (which is implicitly convertible to int) is supported + // because appropriate "move_assignable" is in concept. + double double9 = 9.5; + x = std::move(double9); // truncates value + BOOST_CHECK_EQUAL(any_cast<const test_type3&>(x).value, 9.0); +} + +#endif diff --git a/src/boost/libs/type_erasure/test/test_binding.cpp b/src/boost/libs/type_erasure/test/test_binding.cpp new file mode 100644 index 000000000..9a731a49c --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_binding.cpp @@ -0,0 +1,128 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/static_binding.hpp> +#include <boost/type_erasure/binding.hpp> +#include <boost/type_erasure/placeholder.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/map.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_AUTO_TEST_CASE(test_empty_binding) +{ + boost::mpl::map<> m1; + binding<boost::mpl::vector<> > b1(m1); + binding<boost::mpl::vector<> > b2(make_binding<boost::mpl::map<> >()); + BOOST_CHECK(b1 == b2); + BOOST_CHECK(!(b1 != b2)); + + boost::mpl::map<boost::mpl::pair<_a, int> > m2; + binding<boost::mpl::vector<> > b3(m2); + BOOST_CHECK(b3 == b1); + BOOST_CHECK(!(b3 != b1)); + binding<boost::mpl::vector<> > b4(make_binding<boost::mpl::map<boost::mpl::pair<_a, int> > >()); + BOOST_CHECK(b4 == b1); + BOOST_CHECK(!(b4 != b1)); + + binding<boost::mpl::vector<> > b5(b1, m1); + BOOST_CHECK(b5 == b1); + BOOST_CHECK(!(b5 != b1)); + binding<boost::mpl::vector<> > b6(b1, make_binding<boost::mpl::map<> >()); + BOOST_CHECK(b6 == b1); + BOOST_CHECK(!(b6 != b1)); + + boost::mpl::map<boost::mpl::pair<_a, _b> > m3; + binding<boost::mpl::vector<> > b7(b1, m3); + BOOST_CHECK(b7 == b1); + BOOST_CHECK(!(b7 != b1)); + binding<boost::mpl::vector<> > b8(b1, make_binding<boost::mpl::map<boost::mpl::pair<_a, _b> > >()); + BOOST_CHECK(b8 == b1); + BOOST_CHECK(!(b8 != b1)); +} + +BOOST_AUTO_TEST_CASE(test_binding_one) +{ + boost::mpl::map<boost::mpl::pair<_a, int> > m1; + binding<typeid_<_a> > b1(m1); + BOOST_CHECK(b1.find<typeid_<_a> >()() == typeid(int)); + binding<typeid_<_a> > b2(make_binding<boost::mpl::map<boost::mpl::pair<_a, int> > >()); + BOOST_CHECK(b2.find<typeid_<_a> >()() == typeid(int)); + BOOST_CHECK(b1 == b2); + BOOST_CHECK(!(b1 != b2)); + + boost::mpl::map<boost::mpl::pair<_a, _a> > m2; + binding<typeid_<_a> > b3(b1, m2); + BOOST_CHECK(b3.find<typeid_<_a> >()() == typeid(int)); + BOOST_CHECK(b3 == b1); + BOOST_CHECK(!(b3 != b1)); + binding<typeid_<_a> > b4(b1, make_binding<boost::mpl::map<boost::mpl::pair<_a, _a> > >()); + BOOST_CHECK(b4.find<typeid_<_a> >()() == typeid(int)); + BOOST_CHECK(b4 == b1); + BOOST_CHECK(!(b4 != b1)); + + boost::mpl::map<boost::mpl::pair<_b, _a> > m3; + binding<typeid_<_b> > b5(b1, m3); + BOOST_CHECK(b5.find<typeid_<_b> >()() == typeid(int)); + binding<typeid_<_b> > b6(b1, make_binding<boost::mpl::map<boost::mpl::pair<_b, _a> > >()); + BOOST_CHECK(b6.find<typeid_<_b> >()() == typeid(int)); +} + +BOOST_AUTO_TEST_CASE(test_binding_two) +{ + boost::mpl::map<boost::mpl::pair<_a, int>, boost::mpl::pair<_b, char> > m1; + binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b1(m1); + BOOST_CHECK(b1.find<typeid_<_a> >()() == typeid(int)); + BOOST_CHECK(b1.find<typeid_<_b> >()() == typeid(char)); + binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b2( + make_binding<boost::mpl::map<boost::mpl::pair<_a, int>, boost::mpl::pair<_b, char> > >()); + BOOST_CHECK(b2.find<typeid_<_a> >()() == typeid(int)); + BOOST_CHECK(b2.find<typeid_<_b> >()() == typeid(char)); + BOOST_CHECK(b1 == b2); + BOOST_CHECK(!(b1 != b2)); + + // select the first + boost::mpl::map<boost::mpl::pair<_a, _a> > m2; + binding<typeid_<_a> > b3(b1, m2); + BOOST_CHECK(b3.find<typeid_<_a> >()() == typeid(int)); + binding<typeid_<_a> > b4(b1, make_binding<boost::mpl::map<boost::mpl::pair<_a, _a> > >()); + BOOST_CHECK(b4.find<typeid_<_a> >()() == typeid(int)); + + // select the second + boost::mpl::map<boost::mpl::pair<_b, _b> > m3; + binding<typeid_<_b> > b5(b1, m3); + BOOST_CHECK(b5.find<typeid_<_b> >()() == typeid(char)); + binding<typeid_<_b> > b6(b1, make_binding<boost::mpl::map<boost::mpl::pair<_b, _b> > >()); + BOOST_CHECK(b6.find<typeid_<_b> >()() == typeid(char)); + + // rename both + boost::mpl::map<boost::mpl::pair<_c, _a>, boost::mpl::pair<_d, _b> > m4; + binding<boost::mpl::vector<typeid_<_c>, typeid_<_d> > > b7(b1, m4); + BOOST_CHECK(b7.find<typeid_<_c> >()() == typeid(int)); + BOOST_CHECK(b7.find<typeid_<_d> >()() == typeid(char)); + binding<boost::mpl::vector<typeid_<_c>, typeid_<_d> > > b8(b1, + make_binding<boost::mpl::map<boost::mpl::pair<_c, _a>, boost::mpl::pair<_d, _b> > >()); + BOOST_CHECK(b8.find<typeid_<_c> >()() == typeid(int)); + BOOST_CHECK(b8.find<typeid_<_d> >()() == typeid(char)); + + // switch the placeholders + boost::mpl::map<boost::mpl::pair<_a, _b>, boost::mpl::pair<_b, _a> > m5; + binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b9(b1, m5); + BOOST_CHECK(b9.find<typeid_<_b> >()() == typeid(int)); + BOOST_CHECK(b9.find<typeid_<_a> >()() == typeid(char)); + binding<boost::mpl::vector<typeid_<_a>, typeid_<_b> > > b10(b1, + make_binding<boost::mpl::map<boost::mpl::pair<_a, _b>, boost::mpl::pair<_b, _a> > >()); + BOOST_CHECK(b10.find<typeid_<_b> >()() == typeid(int)); + BOOST_CHECK(b10.find<typeid_<_a> >()() == typeid(char)); +} diff --git a/src/boost/libs/type_erasure/test/test_binding_of.cpp b/src/boost/libs/type_erasure/test/test_binding_of.cpp new file mode 100644 index 000000000..cfc521055 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_binding_of.cpp @@ -0,0 +1,40 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/binding_of.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_binding_of) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + any<test_concept> x(2); + binding<test_concept> b = binding_of(x); + binding<test_concept> expected( + make_binding< + ::boost::mpl::map< ::boost::mpl::pair<_self, int> > + >()); + BOOST_CHECK(b == expected); +} diff --git a/src/boost/libs/type_erasure/test/test_callable.cpp b/src/boost/libs/type_erasure/test/test_callable.cpp new file mode 100644 index 000000000..2a271651d --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_callable.cpp @@ -0,0 +1,536 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/callable.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/utility/result_of.hpp> +#include <vector> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +int f1_val; +void f1() { ++f1_val; } + +int f2_val; +int f2() { return ++f2_val; } + +BOOST_AUTO_TEST_CASE(test_void) +{ + typedef ::boost::mpl::vector< + common<>, + callable<void()> + > test_concept; + any<test_concept> x1(&f1); + f1_val = 0; + x1(); + BOOST_CHECK_EQUAL(f1_val, 1); + + any<test_concept> x2(&f2); + f2_val = 0; + x2(); + BOOST_CHECK_EQUAL(f2_val, 1); + + typedef ::boost::mpl::vector< + common<>, + callable<int()> + > test_concept_int; + any<test_concept_int> x3(&f2); + f2_val = 0; + int i = x3(); + BOOST_CHECK_EQUAL(i, 1); + BOOST_CHECK_EQUAL(f2_val, 1); +} + +BOOST_AUTO_TEST_CASE(test_void_const) +{ + typedef ::boost::mpl::vector< + common<>, + callable<void(), const _self> + > test_concept; + const any<test_concept> x1(&f1); + f1_val = 0; + x1(); + BOOST_CHECK_EQUAL(f1_val, 1); + + const any<test_concept> x2(&f2); + f2_val = 0; + x2(); + BOOST_CHECK_EQUAL(f2_val, 1); + + typedef ::boost::mpl::vector< + common<>, + callable<int(), const _self> + > test_concept_int; + const any<test_concept_int> x3(&f2); + f2_val = 0; + int i = x3(); + BOOST_CHECK_EQUAL(i, 1); + BOOST_CHECK_EQUAL(f2_val, 1); +} + +int f3_val; +void f3(int i) { f3_val += i; } + +int f4_val; +int f4(int i) { return f4_val += i; } + +BOOST_AUTO_TEST_CASE(test_int) +{ + typedef ::boost::mpl::vector< + common<>, + callable<void(int)> + > test_concept; + any<test_concept> x1(&f3); + f3_val = 1; + x1(3); + BOOST_CHECK_EQUAL(f3_val, 4); + + any<test_concept> x2(&f4); + f4_val = 1; + x2(2); + BOOST_CHECK_EQUAL(f4_val, 3); + + typedef ::boost::mpl::vector< + common<>, + callable<int(int)> + > test_concept_int; + any<test_concept_int> x3(&f4); + f4_val = 1; + int i = x3(4); + BOOST_CHECK_EQUAL(i, 5); + BOOST_CHECK_EQUAL(f4_val, 5); +} + +BOOST_AUTO_TEST_CASE(test_int_const) +{ + typedef ::boost::mpl::vector< + common<>, + callable<void(int), const _self> + > test_concept; + const any<test_concept> x1(&f3); + f3_val = 1; + x1(3); + BOOST_CHECK_EQUAL(f3_val, 4); + + const any<test_concept> x2(&f4); + f4_val = 1; + x2(2); + BOOST_CHECK_EQUAL(f4_val, 3); + + typedef ::boost::mpl::vector< + common<>, + callable<int(int), const _self> + > test_concept_int; + const any<test_concept_int> x3(&f4); + f4_val = 1; + int i = x3(4); + BOOST_CHECK_EQUAL(i, 5); + BOOST_CHECK_EQUAL(f4_val, 5); +} + +BOOST_AUTO_TEST_CASE(test_any) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void(_a)> + > test_concept; + tuple<test_concept, _self, _a> t1(&f3, 3); + any<test_concept> x1(get<0>(t1)); + f3_val = 1; + x1(get<1>(t1)); + BOOST_CHECK_EQUAL(f3_val, 4); + + tuple<test_concept, _self, _a> t2(&f4, 2); + any<test_concept> x2(get<0>(t2)); + f4_val = 1; + x2(get<1>(t2)); + BOOST_CHECK_EQUAL(f4_val, 3); + + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<_a(_a)> + > test_concept_int; + tuple<test_concept_int, _self, _a> t3(&f4, 4); + any<test_concept_int> x3(get<0>(t3)); + f4_val = 1; + int i = any_cast<int>(x3(get<1>(t3))); + BOOST_CHECK_EQUAL(i, 5); + BOOST_CHECK_EQUAL(f4_val, 5); +} + +BOOST_AUTO_TEST_CASE(test_any_const) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void(_a), const _self> + > test_concept; + tuple<test_concept, _self, _a> t1(&f3, 3); + const any<test_concept> x1(get<0>(t1)); + f3_val = 1; + x1(get<1>(t1)); + BOOST_CHECK_EQUAL(f3_val, 4); + + tuple<test_concept, _self, _a> t2(&f4, 2); + const any<test_concept> x2(get<0>(t2)); + f4_val = 1; + x2(get<1>(t2)); + BOOST_CHECK_EQUAL(f4_val, 3); + + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<_a(_a), const _self> + > test_concept_int; + tuple<test_concept_int, _self, _a> t3(&f4, 4); + const any<test_concept_int> x3(get<0>(t3)); + f4_val = 1; + int i = any_cast<int>(x3(get<1>(t3))); + BOOST_CHECK_EQUAL(i, 5); + BOOST_CHECK_EQUAL(f4_val, 5); +} + +int overload1; +int overload2; +int overload3; + +struct overloaded_function +{ + int operator()() const { return ++overload1; } + int operator()(int i) const { return overload2 += i; } + int operator()(short i) const { return overload3 += i; } +}; + +BOOST_AUTO_TEST_CASE(test_result_of) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void()>, + callable<int(int)>, + callable<long(_a)> + > test_concept; + + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, void>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(int)>::type, int>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(any<test_concept, _a>)>::type, long>)); +} + +BOOST_AUTO_TEST_CASE(test_result_of_const) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void(), const _self>, + callable<int(int), const _self>, + callable<long(_a), const _self> + > test_concept; + + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>()>::type, void>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(int)>::type, int>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(any<test_concept, _a>)>::type, long>)); +} + +BOOST_AUTO_TEST_CASE(test_overload) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void()>, + callable<void(int)>, + callable<void(_a)> + > test_concept; + tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3)); + any<test_concept> f(get<0>(t)); + any<test_concept, _a> a(get<1>(t)); + + overload1 = 0; + f(); + BOOST_CHECK_EQUAL(overload1, 1); + + overload2 = 0; + f(2); + BOOST_CHECK_EQUAL(overload2, 2); + + overload3 = 0; + f(a); + BOOST_CHECK_EQUAL(overload3, 3); + + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, void>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(int)>::type, void>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(any<test_concept, _a>)>::type, void>)); +} + +BOOST_AUTO_TEST_CASE(test_overload_return) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<int()>, + callable<int(int)>, + callable<int(_a)> + > test_concept; + tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3)); + any<test_concept> f(get<0>(t)); + any<test_concept, _a> a(get<1>(t)); + + overload1 = 0; + BOOST_CHECK_EQUAL(f(), 1); + BOOST_CHECK_EQUAL(overload1, 1); + + overload2 = 0; + BOOST_CHECK_EQUAL(f(2), 2); + BOOST_CHECK_EQUAL(overload2, 2); + + overload3 = 0; + BOOST_CHECK_EQUAL(f(a), 3); + BOOST_CHECK_EQUAL(overload3, 3); + + //BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, int>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(int)>::type, int>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>(any<test_concept, _a>)>::type, int>)); +} + + +BOOST_AUTO_TEST_CASE(test_overload_const) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void(), const _self>, + callable<void(int), const _self>, + callable<void(_a), const _self> + > test_concept; + tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3)); + any<test_concept> f(get<0>(t)); + any<test_concept, _a> a(get<1>(t)); + + overload1 = 0; + f(); + BOOST_CHECK_EQUAL(overload1, 1); + + overload2 = 0; + f(2); + BOOST_CHECK_EQUAL(overload2, 2); + + overload3 = 0; + f(a); + BOOST_CHECK_EQUAL(overload3, 3); + + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>()>::type, void>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(int)>::type, void>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(any<test_concept, _a>)>::type, void>)); +} + +BOOST_AUTO_TEST_CASE(test_overload_return_const) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<int(), const _self>, + callable<int(int), const _self>, + callable<int(_a), const _self> + > test_concept; + tuple<test_concept, _self, _a> t(overloaded_function(), static_cast<short>(3)); + any<test_concept> f(get<0>(t)); + any<test_concept, _a> a(get<1>(t)); + + overload1 = 0; + BOOST_CHECK_EQUAL(f(), 1); + BOOST_CHECK_EQUAL(overload1, 1); + + overload2 = 0; + BOOST_CHECK_EQUAL(f(2), 2); + BOOST_CHECK_EQUAL(overload2, 2); + + overload3 = 0; + BOOST_CHECK_EQUAL(f(a), 3); + BOOST_CHECK_EQUAL(overload3, 3); + + //BOOST_MPL_ASSERT((boost::is_same<boost::result_of<any<test_concept>()>::type, int>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(int)>::type, int>)); + BOOST_MPL_ASSERT((boost::is_same<boost::result_of<const any<test_concept>(any<test_concept, _a>)>::type, int>)); +} + +struct model_ret_ref +{ + model_ret_ref& operator()() { return *this; } +}; + +BOOST_AUTO_TEST_CASE(test_ref_any_result) +{ + typedef ::boost::mpl::vector< + common<>, + callable<_self&()> + > test_concept; + + any<test_concept> x1 = model_ret_ref(); + any<test_concept, _self&> x2(x1()); + BOOST_CHECK_EQUAL(any_cast<model_ret_ref*>(&x1), any_cast<model_ret_ref*>(&x2)); +} + +int f_ret_ref_val; +int& f_ret_ref() { return f_ret_ref_val; } + +BOOST_AUTO_TEST_CASE(test_ref_int_result) +{ + typedef ::boost::mpl::vector< + common<>, + callable<int&()> + > test_concept; + + any<test_concept> x1 = f_ret_ref; + int& result = x1(); + BOOST_CHECK_EQUAL(&result, &f_ret_ref_val); +} + +struct model_ret_cref +{ + const model_ret_cref& operator()() { return *this; } +}; + +BOOST_AUTO_TEST_CASE(test_cref_any_result) +{ + typedef ::boost::mpl::vector< + common<>, + callable<const _self&()> + > test_concept; + + any<test_concept> x1 = model_ret_ref(); + any<test_concept, const _self&> x2(x1()); + BOOST_CHECK_EQUAL(any_cast<const model_ret_cref*>(&x1), any_cast<const model_ret_cref*>(&x2)); +} + +int f_ret_cref_val; +const int& f_ret_cref() { return f_ret_cref_val; } + +BOOST_AUTO_TEST_CASE(test_cref_int_result) +{ + typedef ::boost::mpl::vector< + common<>, + callable<const int&()> + > test_concept; + + any<test_concept> x1 = f_ret_cref; + const int& result = x1(); + BOOST_CHECK_EQUAL(&result, &f_ret_cref_val); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +int f_rv_value = 0; +void f_rv(int&& i) { f_rv_value += i; } + +BOOST_AUTO_TEST_CASE(test_rvalue_int) +{ + typedef ::boost::mpl::vector< + common<>, + callable<void(int&&)> + > test_concept; + any<test_concept> f(&f_rv); + + f_rv_value = 1; + f(2); + BOOST_CHECK_EQUAL(f_rv_value, 3); +} + +BOOST_AUTO_TEST_CASE(test_rvalue_any) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void(_a&&)> + > test_concept; + + tuple<test_concept, _self, _a> t1(&f_rv, 3); + any<test_concept> x1(get<0>(t1)); + f_rv_value = 1; + x1(std::move(get<1>(t1))); + BOOST_CHECK_EQUAL(f_rv_value, 4); +} + +BOOST_AUTO_TEST_CASE(test_const_rvalue_int) +{ + typedef ::boost::mpl::vector< + common<>, + callable<void(int&&), const _self> + > test_concept; + const any<test_concept> f(&f_rv); + + f_rv_value = 1; + f(2); + BOOST_CHECK_EQUAL(f_rv_value, 3); +} + +BOOST_AUTO_TEST_CASE(test_const_rvalue_any) +{ + typedef ::boost::mpl::vector< + common<>, + common<_a>, + callable<void(_a&&), const _self> + > test_concept; + + tuple<test_concept, _self, _a> t1(&f_rv, 3); + const any<test_concept> x1(get<0>(t1)); + f_rv_value = 1; + x1(std::move(get<1>(t1))); + BOOST_CHECK_EQUAL(f_rv_value, 4); +} + +struct model_ret_rref +{ + model_ret_rref&& operator()() { return std::move(*this); } +}; + +BOOST_AUTO_TEST_CASE(test_rvalue_any_result) +{ + typedef ::boost::mpl::vector< + common<>, + callable<_self&&()> + > test_concept; + + any<test_concept> x1 = model_ret_rref(); + any<test_concept, _self&&> x2(x1()); + BOOST_CHECK_EQUAL(any_cast<model_ret_rref*>(&x1), any_cast<model_ret_rref*>(&x2)); +} + +int f_ret_rv_val; +int&& f_ret_rv() { return std::move(f_ret_rv_val); } + +BOOST_AUTO_TEST_CASE(test_rvalue_int_result) +{ + typedef ::boost::mpl::vector< + common<>, + callable<int&&()> + > test_concept; + + any<test_concept> x1 = f_ret_rv; + int&& result = x1(); + BOOST_CHECK_EQUAL(&result, &f_ret_rv_val); +} + +#endif diff --git a/src/boost/libs/type_erasure/test/test_construct.cpp b/src/boost/libs/type_erasure/test/test_construct.cpp new file mode 100644 index 000000000..7836b9216 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_construct.cpp @@ -0,0 +1,1198 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/binding_of.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/tuple/tuple.hpp> +#include <vector> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_implicit) { + any<common<> > x = 1; + BOOST_CHECK_EQUAL(any_cast<int>(x), 1); +} + +void func() {} + +BOOST_AUTO_TEST_CASE(test_decay) { + char array[] = "Hello World!"; + const char carray[] = "Hello World!"; + + any<common<> > x1(array); + any<common<> > y1(func); + any<common<> > z1(carray); + BOOST_CHECK_EQUAL(any_cast<char *>(x1), &array[0]); + BOOST_CHECK(any_cast<void(*)()>(y1) == &func); + BOOST_CHECK_EQUAL(any_cast<const char *>(z1), &carray[0]); + + any<common<> > x2(array, make_binding<boost::mpl::map<boost::mpl::pair<_self, char *> > >()); + any<common<> > y2(func, make_binding<boost::mpl::map<boost::mpl::pair<_self, void(*)()> > >()); + any<common<> > z2(carray, make_binding<boost::mpl::map<boost::mpl::pair<_self, const char *> > >()); + BOOST_CHECK_EQUAL(any_cast<char *>(x2), &array[0]); + BOOST_CHECK(any_cast<void(*)()>(y2) == &func); + BOOST_CHECK_EQUAL(any_cast<const char *>(z2), &carray[0]); + + static_binding<boost::mpl::map<boost::mpl::pair<_self, char *> > > bx3; + static_binding<boost::mpl::map<boost::mpl::pair<_self, void (*)()> > > by3; + static_binding<boost::mpl::map<boost::mpl::pair<_self, const char *> > > bz3; + any<common<> > x3(array, bx3); + any<common<> > y3(func, by3); + any<common<> > z3(carray, bz3); + BOOST_CHECK_EQUAL(any_cast<char *>(x3), &array[0]); + BOOST_CHECK(any_cast<void(*)()>(y3) == &func); + BOOST_CHECK_EQUAL(any_cast<const char *>(z3), &carray[0]); +} + +enum { + lvalue, + const_lvalue, + rvalue +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + = lvalue +#endif +}; + +template<class T> +int make_arg_type(); + +template<> +int make_arg_type<int>() { return rvalue; } +template<> +int make_arg_type<int&>() { return lvalue; } +template<> +int make_arg_type<const int&>() { return const_lvalue; } + +enum { id_int = 4, id_copy = 8 }; + +std::vector<int> make_vector() { return std::vector<int>(); } + +template<class T> +std::vector<T> make_vector(T t0) { + std::vector<T> result; + result.push_back(t0); + return result; +} +template<class T> +std::vector<T> make_vector(T t0, T t1) { + std::vector<T> result; + result.push_back(t0); + result.push_back(t1); + return result; +} + +#ifdef BOOST_MSVC +#pragma warning(disable:4521) // multiple copy constructors specified +#endif + +struct test_class +{ + + test_class() {} + + test_class(const test_class &) + : args(make_vector(const_lvalue | id_copy)) + {} + + test_class(test_class &) + : args(make_vector(lvalue | id_copy)) + {} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + test_class(test_class &&) + : args(make_vector(rvalue | id_copy)) + {} + + template<class T0> + test_class(T0&& t0) + : args(make_vector(t0 | make_arg_type<T0>())) + {} + + template<class T0, class T1> + test_class(T0&& t0, T1&& t1) + : args(make_vector(t0 | make_arg_type<T0>(), t1 | make_arg_type<T1>())) + {} + +#else + + test_class(int& i0) + : args(make_vector(i0 | lvalue)) + {} + test_class(const int& i0) + : args(make_vector(i0 | const_lvalue)) + {} + test_class(int& i0, int& i1) + : args(make_vector(i0 | lvalue, i1 | lvalue)) + {} + test_class(int& i0, const int& i1) + : args(make_vector(i0 | lvalue, i1 | const_lvalue)) + {} + test_class(const int& i0, int& i1) + : args(make_vector(i0 | const_lvalue, i1 | lvalue)) + {} + test_class(const int& i0, const int& i1) + : args(make_vector(i0 | const_lvalue, i1 | const_lvalue)) + {} + +#endif + std::vector<int> args; +}; + +template<class T> +struct make_arg_impl; + +template<> +struct make_arg_impl<int> +{ + static int apply() + { + return id_int; + } +}; + +template<class Concept> +struct make_arg_impl<binding<Concept> > +{ + static binding<Concept> apply() + { + return make_binding< ::boost::mpl::map< + ::boost::mpl::pair<_a, test_class>, + ::boost::mpl::pair<_b, int> + > >(); + } +}; + +template<class Concept> +struct make_arg_impl<any<Concept, _a>&> +{ + static any<Concept, _a>& apply() + { + static any<Concept, _a> result( + test_class(), + make_binding< ::boost::mpl::map< + ::boost::mpl::pair<_a, test_class>, + ::boost::mpl::pair<_b, int> + > >()); + return result; + } +}; + +template<class Concept> +struct make_arg_impl<any<Concept, _b>&> +{ + static any<Concept, _b>& apply() + { + static any<Concept, _b> result( + (int)id_int, + make_binding< ::boost::mpl::map< + ::boost::mpl::pair<_a, test_class>, + ::boost::mpl::pair<_b, int> + > >()); + return result; + } +}; + +template<class Concept> +struct make_arg_impl<any<Concept, _a> > +{ + static any<Concept, _a> apply() + { + return make_arg_impl<any<Concept, _a>&>::apply(); + } +}; + +template<class Concept> +struct make_arg_impl<any<Concept, _b> > +{ + static any<Concept, _b> apply() + { + return make_arg_impl<any<Concept, _b>&>::apply(); + } +}; + +template<class Concept, class T> +struct make_arg_impl<any<Concept, T&> > +{ + static any<Concept, T&> apply() + { + return make_arg_impl<any<Concept, T>&>::apply(); + } +}; + +template<class Concept, class T> +struct make_arg_impl<any<Concept, const T&> > +{ + static any<Concept, const T&> apply() + { + return make_arg_impl<any<Concept, T>&>::apply(); + } +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template<class Concept, class T> +struct make_arg_impl<any<Concept, T&&> > +{ + static any<Concept, T&&> apply() + { + return std::move(make_arg_impl<any<Concept, T>&>::apply()); + } +}; + +#endif + +template<class T> +struct make_arg_impl<const T> : make_arg_impl<T> {}; + +template<class T> +struct make_arg_impl<T&> +{ + static T& apply() + { + static T result = make_arg_impl<T>::apply(); + return result; + } +}; +template<class T> +struct make_arg_impl<const T&> +{ + static T& apply() + { + return make_arg_impl<T&>::apply(); + } +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template<class T> +struct make_arg_impl<T&&> +{ + static T&& apply() + { + return std::move(make_arg_impl<T&>::apply()); + } +}; + +#endif + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + +template<class T> +T make_arg() +{ + return make_arg_impl<T>::apply(); +} + +#else + +template<class T> +T&& make_arg() +{ + return make_arg_impl<T&&>::apply(); +} + +#endif + +int get_value(int i) { return i; } +template<class T> +int get_value(const T& t) { return any_cast<int>(t); } + +template<class Sig, class Args> +struct tester; + +template<class Concept, class T> +struct tester<Concept, void(T)> +{ + static std::vector<int> apply() + { + any<Concept, _a> x(make_arg<T>()); + const test_class& result = any_cast<const test_class&>(x); + return result.args; + } +}; + +template<class Concept, class T0, class T1> +struct tester<Concept, void(T0, T1)> +{ + static std::vector<int> apply() + { + any<Concept, _a> x(make_arg<T0>(), make_arg<T1>()); + const test_class& result = any_cast<const test_class&>(x); + return result.args; + } +}; + +template<class Concept, class T0, class T1, class T2> +struct tester<Concept, void(T0, T1, T2)> +{ + static std::vector<int> apply() + { + any<Concept, _a> x(make_arg<T0>(), make_arg<T1>(), make_arg<T2>()); + const test_class& result = any_cast<const test_class&>(x); + return result.args; + } +}; + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +// We need copy_constructible in order to get an rvalue. +#define CONSTRUCT_COMMON(p) common<p> +#else +// Don't include the copy constructor if we don't +// need it, as it can hide the non-const copy constructor. +#define CONSTRUCT_COMMON(p) destructible<p>, typeid_<p> +#endif + +#define TEST_CONSTRUCT(sig, args, expected_) \ +{\ + typedef ::boost::mpl::vector<\ + CONSTRUCT_COMMON(_a), \ + common<_b>,\ + constructible<sig>,\ + extra\ + > C;\ + std::vector<int> result = tester<C, void args>::apply();\ + std::vector<int> expected = make_vector expected_;\ + BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), \ + expected.begin(), expected.end());\ +} + +typedef ::boost::mpl::vector< + ::boost::mpl::vector<>, + ::boost::type_erasure::relaxed +> maybe_relaxed; + +BOOST_AUTO_TEST_CASE_TEMPLATE(test_default, extra, maybe_relaxed) +{ + TEST_CONSTRUCT(_a(), (binding<C>), ()); + TEST_CONSTRUCT(_a(), (binding<C>&), ()); + TEST_CONSTRUCT(_a(), (const binding<C>&), ()); +} + +// test all forms of direct construction that take 1 argument +BOOST_AUTO_TEST_CASE_TEMPLATE(test_construct1, extra, maybe_relaxed) +{ + // construction from int + TEST_CONSTRUCT(_a(int&), (binding<C>, int&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(int&), (binding<C>&, int&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(int&), (const binding<C>&, int&), (lvalue | id_int)); + + TEST_CONSTRUCT(_a(const int&), (binding<C>, int), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (binding<C>, int&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (binding<C>, const int&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (binding<C>&, int), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (binding<C>&, int&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (binding<C>&, const int&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (const binding<C>&, int), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (const binding<C>&, int&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const int&), (const binding<C>&, const int&), (const_lvalue | id_int)); + + TEST_CONSTRUCT(_a(int), (binding<C>, int), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (binding<C>, int&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (binding<C>, const int&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (binding<C>&, int), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (binding<C>&, int&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (binding<C>&, const int&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (const binding<C>&, int), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (const binding<C>&, int&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int), (const binding<C>&, const int&), (rvalue | id_int)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_CONSTRUCT(_a(int&&), (binding<C>, int), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int&&), (binding<C>&, int), (rvalue | id_int)); + TEST_CONSTRUCT(_a(int&&), (const binding<C>&, int), (rvalue | id_int)); +#endif + + // Test same any type + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + // ambiguous with the copy constructor in C++03 + TEST_CONSTRUCT(_a(_a&), (any<C, _a>&), (lvalue | id_copy)); + TEST_CONSTRUCT(_a(_a&), (binding<C>, any<C, _a>&), (lvalue | id_copy)); + TEST_CONSTRUCT(_a(_a&), (binding<C>&, any<C, _a>&), (lvalue | id_copy)); + TEST_CONSTRUCT(_a(_a&), (const binding<C>&, any<C, _a>&), (lvalue | id_copy)); +#endif + + TEST_CONSTRUCT(_a(const _a&), (any<C, _a>), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (any<C, _a>&), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (const any<C, _a>&), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (binding<C>, any<C, _a>), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (binding<C>, any<C, _a>&), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (binding<C>, const any<C, _a>&), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (binding<C>&, any<C, _a>), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (binding<C>&, any<C, _a>&), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (binding<C>&, const any<C, _a>&), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (const binding<C>&, any<C, _a>), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (const binding<C>&, any<C, _a>&), (const_lvalue | id_copy)); + TEST_CONSTRUCT(_a(const _a&), (const binding<C>&, const any<C, _a>&), (const_lvalue | id_copy)); + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_CONSTRUCT(_a(_a&&), (any<C, _a>), (rvalue | id_copy)); + TEST_CONSTRUCT(_a(_a&&), (binding<C>, any<C, _a>), (rvalue | id_copy)); + TEST_CONSTRUCT(_a(_a&&), (binding<C>&, any<C, _a>), (rvalue | id_copy)); + TEST_CONSTRUCT(_a(_a&&), (const binding<C>&, any<C, _a>), (rvalue | id_copy)); +#endif + +#endif + + // test other any type + TEST_CONSTRUCT(_a(_b&), (any<C, _b>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>, any<C, _b>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>&, any<C, _b>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (const binding<C>&, any<C, _b>&), (lvalue | id_int)); + + TEST_CONSTRUCT(_a(const _b&), (any<C, _b>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (any<C, _b>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const any<C, _b>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, _b>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, _b>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, const any<C, _b>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, _b>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, _b>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, const any<C, _b>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, _b>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, _b>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, const any<C, _b>&), (const_lvalue | id_int)); + + TEST_CONSTRUCT(_a(_b), (any<C, _b>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (any<C, _b>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const any<C, _b>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, _b>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, _b>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, const any<C, _b>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, _b>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, _b>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, const any<C, _b>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, _b>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, _b>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, const any<C, _b>&), (rvalue | id_int)); + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + TEST_CONSTRUCT(_a(_b&&), (any<C, _b>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>, any<C, _b>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>&, any<C, _b>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (const binding<C>&, any<C, _b>), (rvalue | id_int)); +#endif + +#endif + + // test any reference type + TEST_CONSTRUCT(_a(_b&), (any<C, _b&>), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (any<C, _b&>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (const any<C, _b&>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>, any<C, _b&>), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>, any<C, _b&>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>, const any<C, _b&>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>&, any<C, _b&>), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>&, any<C, _b&>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (binding<C>&, const any<C, _b&>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (const binding<C>&, any<C, _b&>), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (const binding<C>&, any<C, _b&>&), (lvalue | id_int)); + TEST_CONSTRUCT(_a(_b&), (const binding<C>&, const any<C, _b&>&), (lvalue | id_int)); + + TEST_CONSTRUCT(_a(const _b&), (any<C, _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (any<C, _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const any<C, _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, const any<C, _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, const any<C, _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, const any<C, _b&>&), (const_lvalue | id_int)); + + TEST_CONSTRUCT(_a(_b), (any<C, _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (any<C, _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const any<C, _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, const any<C, _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, const any<C, _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, const any<C, _b&>&), (rvalue | id_int)); + + // test const any reference type + TEST_CONSTRUCT(_a(const _b&), (any<C, const _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (any<C, const _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const any<C, const _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, const _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, const _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, const any<C, const _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, const _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, const _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, const any<C, const _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, const _b&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, const _b&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, const any<C, const _b&>&), (const_lvalue | id_int)); + + TEST_CONSTRUCT(_a(_b), (any<C, const _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (any<C, const _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const any<C, const _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, const _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, const _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, const any<C, const _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, const _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, const _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, const any<C, const _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, const _b&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, const _b&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, const any<C, const _b&>&), (rvalue | id_int)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + // test any rvalue reference type + TEST_CONSTRUCT(_a(const _b&), (any<C, _b&&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (any<C, _b&&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const any<C, _b&&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, _b&&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, any<C, _b&&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>, const any<C, _b&&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, _b&&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, any<C, _b&&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (binding<C>&, const any<C, _b&&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, _b&&>), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, any<C, _b&&>&), (const_lvalue | id_int)); + TEST_CONSTRUCT(_a(const _b&), (const binding<C>&, const any<C, _b&&>&), (const_lvalue | id_int)); + + TEST_CONSTRUCT(_a(_b), (any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>, const any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (binding<C>&, const any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b), (const binding<C>&, const any<C, _b&&>&), (rvalue | id_int)); + + TEST_CONSTRUCT(_a(_b&&), (any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (const any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>, any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>, any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>, const any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>&, any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>&, any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (binding<C>&, const any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (const binding<C>&, any<C, _b&&>), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (const binding<C>&, any<C, _b&&>&), (rvalue | id_int)); + TEST_CONSTRUCT(_a(_b&&), (const binding<C>&, const any<C, _b&&>&), (rvalue | id_int)); + +#endif + +} + +// test constructors with 2 parameters +BOOST_AUTO_TEST_CASE_TEMPLATE(test_construct2, extra, maybe_relaxed) +{ + TEST_CONSTRUCT(_a(int, int), (binding<C>, int, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, int, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, int, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, int&, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, int&, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, int&, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, const int&, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, const int&, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>, const int&, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, int, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, int, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, int, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, int&, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, int&, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, int&, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, const int&, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, const int&, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (binding<C>&, const int&, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, int, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, int, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, int, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, int&, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, int&, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, int&, const int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, const int&, int), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, const int&, int&), (rvalue | id_int, rvalue | id_int)); + TEST_CONSTRUCT(_a(int, int), (const binding<C>&, const int&, const int&), (rvalue | id_int, rvalue | id_int)); +} + +BOOST_AUTO_TEST_CASE(test_overload) +{ + typedef ::boost::mpl::vector< + common<_a>, + common<_b>, + constructible<_a(_b)>, + constructible<_a(std::size_t)> + > test_concept; + typedef ::boost::mpl::map< + ::boost::mpl::pair<_a, std::vector<int> >, + ::boost::mpl::pair<_b, std::size_t> + > types; + binding<test_concept> table = make_binding<types>(); + any<test_concept, _b> x(static_cast<std::size_t>(10), make_binding<types>()); + any<test_concept, _a> y(x); + any<test_concept, _a> z(table, 17); + std::vector<int> vec1(any_cast<std::vector<int> >(y)); + BOOST_CHECK_EQUAL(vec1.size(), 10u); + std::vector<int> vec2(any_cast<std::vector<int> >(z)); + BOOST_CHECK_EQUAL(vec2.size(), 17u); +} + +template<class T> +T as_rvalue(const T& arg) { return arg; } +template<class T> +const T& as_const(const T& arg) { return arg; } + +BOOST_AUTO_TEST_CASE(test_from_int_with_binding) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + static_binding<boost::mpl::map<boost::mpl::pair<_self, int> > > binding = + make_binding<boost::mpl::map<boost::mpl::pair<_self, int> > >(); + int value = 4; + + any<test_concept> x1(value, binding); + BOOST_CHECK_EQUAL(any_cast<int>(x1), 4); + any<test_concept> x2(value, as_rvalue(binding)); + BOOST_CHECK_EQUAL(any_cast<int>(x2), 4); + any<test_concept> x3(value, as_const(binding)); + BOOST_CHECK_EQUAL(any_cast<int>(x3), 4); + + any<test_concept> y1(as_rvalue(value), binding); + BOOST_CHECK_EQUAL(any_cast<int>(y1), 4); + any<test_concept> y2(as_rvalue(value), as_rvalue(binding)); + BOOST_CHECK_EQUAL(any_cast<int>(y2), 4); + any<test_concept> y3(as_rvalue(value), as_const(binding)); + BOOST_CHECK_EQUAL(any_cast<int>(y3), 4); + + any<test_concept> z1(as_const(value), binding); + BOOST_CHECK_EQUAL(any_cast<int>(z1), 4); + any<test_concept> z2(as_const(value), as_rvalue(binding)); + BOOST_CHECK_EQUAL(any_cast<int>(z2), 4); + any<test_concept> z3(as_const(value), as_const(binding)); + BOOST_CHECK_EQUAL(any_cast<int>(z3), 4); +} + +BOOST_AUTO_TEST_CASE(test_copy) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + any<test_concept> x(4); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<test_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<test_concept> z(as_rvalue(x)); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<test_concept> w(as_const(x)); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_copy_implicit) +{ + typedef ::boost::mpl::vector<common<>, common<_a> > test_concept; + any<test_concept> x(4, make_binding< ::boost::mpl::map< ::boost::mpl::pair<_self, int>, ::boost::mpl::pair<_a, int> > >()); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + + any<test_concept> y = x; + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<test_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<test_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_convert) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<> > dst_concept; + any<src_concept> x(4); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind) +{ + typedef ::boost::mpl::vector<common<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + any<src_concept> x(4); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y = x; + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + any<src_concept> x(4); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + static_binding<map> s_table(make_binding<map>()); + binding<dst_concept> table(make_binding<types>()); + + any<src_concept> x(4); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + + // lvalues + any<dst_concept, _a> y1(x, s_table); + BOOST_CHECK_EQUAL(any_cast<int>(y1), 4); + any<dst_concept, _a> y2(x, as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y2), 4); + any<dst_concept, _a> y3(x, as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y3), 4); + any<dst_concept, _a> z1(x, table); + BOOST_CHECK_EQUAL(any_cast<int>(z1), 4); + any<dst_concept, _a> z2(x, as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z2), 4); + any<dst_concept, _a> z3(x, as_const(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z3), 4); + + // rvalues + any<dst_concept, _a> ry1(as_rvalue(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(ry1), 4); + any<dst_concept, _a> ry2(as_rvalue(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry2), 4); + any<dst_concept, _a> ry3(as_rvalue(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry3), 4); + any<dst_concept, _a> rz1(as_rvalue(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(rz1), 4); + any<dst_concept, _a> rz2(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz2), 4); + any<dst_concept, _a> rz3(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz3), 4); + + // const lvalues + any<dst_concept, _a> cy1(as_const(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(cy1), 4); + any<dst_concept, _a> cy2(as_const(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy2), 4); + any<dst_concept, _a> cy3(as_const(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy3), 4); + any<dst_concept, _a> cz1(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(cz1), 4); + any<dst_concept, _a> cz2(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz2), 4); + any<dst_concept, _a> cz3(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz3), 4); +} + +BOOST_AUTO_TEST_CASE(test_copy_from_ref) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 4; + any<test_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<test_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<test_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<test_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_convert_from_ref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_from_ref) +{ + typedef ::boost::mpl::vector<common<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_from_ref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding_from_ref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + static_binding<map> s_table(make_binding<map>()); + binding<dst_concept> table(make_binding<types>()); + + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + + // lvalues + any<dst_concept, _a> y1(x, s_table); + BOOST_CHECK_EQUAL(any_cast<int>(y1), 4); + any<dst_concept, _a> y2(x, as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y2), 4); + any<dst_concept, _a> y3(x, as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y3), 4); + any<dst_concept, _a> z1(x, table); + BOOST_CHECK_EQUAL(any_cast<int>(z1), 4); + any<dst_concept, _a> z2(x, as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z2), 4); + any<dst_concept, _a> z3(x, as_const(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z3), 4); + + // rvalues + any<dst_concept, _a> ry1(as_rvalue(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(ry1), 4); + any<dst_concept, _a> ry2(as_rvalue(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry2), 4); + any<dst_concept, _a> ry3(as_rvalue(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry3), 4); + any<dst_concept, _a> rz1(as_rvalue(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(rz1), 4); + any<dst_concept, _a> rz2(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz2), 4); + any<dst_concept, _a> rz3(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz3), 4); + + // const lvalues + any<dst_concept, _a> cy1(as_const(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(cy1), 4); + any<dst_concept, _a> cy2(as_const(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy2), 4); + any<dst_concept, _a> cy3(as_const(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy3), 4); + any<dst_concept, _a> cz1(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(cz1), 4); + any<dst_concept, _a> cz2(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz2), 4); + any<dst_concept, _a> cz3(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz3), 4); +} + +BOOST_AUTO_TEST_CASE(test_copy_from_cref) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 4; + any<test_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<test_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<test_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<test_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_convert_from_cref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<> > dst_concept; + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_from_cref) +{ + typedef ::boost::mpl::vector<common<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_from_cref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding_from_cref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + static_binding<map> s_table(make_binding<map>()); + binding<dst_concept> table(make_binding<types>()); + + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + + // lvalues + any<dst_concept, _a> y1(x, s_table); + BOOST_CHECK_EQUAL(any_cast<int>(y1), 4); + any<dst_concept, _a> y2(x, as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y2), 4); + any<dst_concept, _a> y3(x, as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y3), 4); + any<dst_concept, _a> z1(x, table); + BOOST_CHECK_EQUAL(any_cast<int>(z1), 4); + any<dst_concept, _a> z2(x, as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z2), 4); + any<dst_concept, _a> z3(x, as_const(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z3), 4); + + // rvalues + any<dst_concept, _a> ry1(as_rvalue(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(ry1), 4); + any<dst_concept, _a> ry2(as_rvalue(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry2), 4); + any<dst_concept, _a> ry3(as_rvalue(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry3), 4); + any<dst_concept, _a> rz1(as_rvalue(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(rz1), 4); + any<dst_concept, _a> rz2(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz2), 4); + any<dst_concept, _a> rz3(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz3), 4); + + // const lvalues + any<dst_concept, _a> cy1(as_const(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(cy1), 4); + any<dst_concept, _a> cy2(as_const(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy2), 4); + any<dst_concept, _a> cy3(as_const(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy3), 4); + any<dst_concept, _a> cz1(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(cz1), 4); + any<dst_concept, _a> cz2(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz2), 4); + any<dst_concept, _a> cz3(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz3), 4); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +struct move_only +{ + explicit move_only(int i) : value(i) {} + move_only(move_only&& other) : value(other.value) { other.value = 0; } + int value; +private: + move_only(const move_only&); +}; + +BOOST_AUTO_TEST_CASE(test_move_only) +{ + typedef ::boost::mpl::vector<destructible<>, typeid_<> > test_concept; + move_only source(2); + any<test_concept> x(std::move(source)); + BOOST_CHECK_EQUAL(source.value, 0); + BOOST_CHECK_EQUAL(any_cast<move_only&>(x).value, 2); +} + +BOOST_AUTO_TEST_CASE(test_copy_from_rref) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 4; + any<test_concept, _self&&> x(std::move(i)); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<test_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<test_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<test_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_convert_from_rref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<> > dst_concept; + int i = 4; + any<src_concept, _self&&> x(std::move(i)); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_from_rref) +{ + typedef ::boost::mpl::vector<common<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + int i = 4; + any<src_concept, _self&&> x(std::move(i)); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_from_rref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + int i = 4; + any<src_concept, _self&&> x(std::move(i)); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + any<dst_concept, _a> y(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 4); + any<dst_concept, _a> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int>(z), 4); + any<dst_concept, _a> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int>(w), 4); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding_from_rref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + static_binding<map> s_table(make_binding<map>()); + binding<dst_concept> table(make_binding<types>()); + + int i = 4; + any<src_concept, _self&&> x(std::move(i)); + BOOST_CHECK_EQUAL(any_cast<int>(x), 4); + + // lvalues + any<dst_concept, _a> y1(x, s_table); + BOOST_CHECK_EQUAL(any_cast<int>(y1), 4); + any<dst_concept, _a> y2(x, as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y2), 4); + any<dst_concept, _a> y3(x, as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(y3), 4); + any<dst_concept, _a> z1(x, table); + BOOST_CHECK_EQUAL(any_cast<int>(z1), 4); + any<dst_concept, _a> z2(x, as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z2), 4); + any<dst_concept, _a> z3(x, as_const(table)); + BOOST_CHECK_EQUAL(any_cast<int>(z3), 4); + + // rvalues + any<dst_concept, _a> ry1(as_rvalue(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(ry1), 4); + any<dst_concept, _a> ry2(as_rvalue(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry2), 4); + any<dst_concept, _a> ry3(as_rvalue(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(ry3), 4); + any<dst_concept, _a> rz1(as_rvalue(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(rz1), 4); + any<dst_concept, _a> rz2(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz2), 4); + any<dst_concept, _a> rz3(as_rvalue(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(rz3), 4); + + // const lvalues + any<dst_concept, _a> cy1(as_const(x), s_table); + BOOST_CHECK_EQUAL(any_cast<int>(cy1), 4); + any<dst_concept, _a> cy2(as_const(x), as_rvalue(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy2), 4); + any<dst_concept, _a> cy3(as_const(x), as_const(s_table)); + BOOST_CHECK_EQUAL(any_cast<int>(cy3), 4); + any<dst_concept, _a> cz1(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<int>(cz1), 4); + any<dst_concept, _a> cz2(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz2), 4); + any<dst_concept, _a> cz3(as_const(x), as_rvalue(table)); + BOOST_CHECK_EQUAL(any_cast<int>(cz3), 4); +} + +#endif diff --git a/src/boost/libs/type_erasure/test/test_construct_cref.cpp b/src/boost/libs/type_erasure/test/test_construct_cref.cpp new file mode 100644 index 000000000..b2e428a71 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_construct_cref.cpp @@ -0,0 +1,283 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/relaxed.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +template<class T> +T as_rvalue(const T& arg) { return arg; } +template<class T> +const T& as_const(const T& arg) { return arg; } + +BOOST_AUTO_TEST_CASE(test_implicit) { + int i = 4; + any<common<>, const _self&> x = i; + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); +} + +BOOST_AUTO_TEST_CASE(test_from_int_with_binding) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 4; + any<test_concept, const _self&> x(i, make_binding<boost::mpl::map<boost::mpl::pair<_self, int> > >()); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); +} + +BOOST_AUTO_TEST_CASE(test_copy) +{ + typedef ::boost::mpl::vector<typeid_<> > test_concept; + int i = 4; + any<test_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<test_concept, const _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<test_concept, const _self&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<test_concept, const _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_convert) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<> > dst_concept; + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _self&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<dst_concept, const _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind) +{ + typedef ::boost::mpl::vector<typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _a&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<dst_concept, const _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _a&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<dst_concept, const _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + binding<dst_concept> table(make_binding<types>()); + + int i = 4; + any<src_concept, const _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _a&> y(x, make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _a&> z(x, table); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + + any<dst_concept, const _a&> cy(as_const(x), make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<const int*>(&cy), &i); + any<dst_concept, const _a&> cz(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<const int*>(&cz), &i); +} + +BOOST_AUTO_TEST_CASE(test_copy_from_ref) +{ + typedef ::boost::mpl::vector<typeid_<> > test_concept; + int i = 4; + any<test_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<test_concept, const _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<test_concept, const _self&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<test_concept, const _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_convert_from_ref) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _self&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<dst_concept, const _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind_from_ref) +{ + typedef ::boost::mpl::vector<typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _a&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<dst_concept, const _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_from_ref) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _a&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + any<dst_concept, const _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding_from_ref) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + binding<dst_concept> table(make_binding<types>()); + + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), &i); + any<dst_concept, const _a&> y(x, make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); + any<dst_concept, const _a&> z(x, table); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), &i); + + any<dst_concept, const _a&> cy(as_const(x), make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<const int*>(&cy), &i); + any<dst_concept, const _a&> cz(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<const int*>(&cz), &i); +} + +BOOST_AUTO_TEST_CASE(test_copy_from_value) +{ + typedef ::boost::mpl::vector<copy_constructible<>, typeid_<> > test_concept; + any<test_concept> x(4); + const int* ip = any_cast<const int*>(&x); + any<test_concept, const _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), ip); + BOOST_CHECK_EQUAL(any_cast<int>(any<test_concept, const _self&>(as_rvalue(x))), 4); + any<test_concept, const _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), ip); +} + +BOOST_AUTO_TEST_CASE(test_convert_from_value) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<> > dst_concept; + any<src_concept> x(4); + const int* ip = any_cast<const int*>(&x); + any<dst_concept, const _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), ip); + BOOST_CHECK_EQUAL(any_cast<int>(any<dst_concept, const _self&>(as_rvalue(x))), 4); + any<dst_concept, const _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), ip); +} + +BOOST_AUTO_TEST_CASE(test_rebind_from_value) +{ + typedef ::boost::mpl::vector<copy_constructible<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<copy_constructible<_a>, typeid_<_a> > dst_concept; + any<src_concept> x(4); + const int* ip = any_cast<const int*>(&x); + any<dst_concept, const _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), ip); + BOOST_CHECK_EQUAL(any_cast<int>(any<dst_concept, const _a&>(as_rvalue(x))), 4); + any<dst_concept, const _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), ip); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_from_value) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + any<src_concept> x(4); + const int* ip = any_cast<const int*>(&x); + any<dst_concept, const _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), ip); + BOOST_CHECK_EQUAL(any_cast<int>(any<dst_concept, const _a&>(as_rvalue(x))), 4); + any<dst_concept, const _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&w), ip); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding_from_value) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + binding<dst_concept> table(make_binding<types>()); + + any<src_concept> x(4); + const int* ip = any_cast<const int*>(&x); + any<dst_concept, const _a&> y(x, make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), ip); + any<dst_concept, const _a&> z(x, table); + BOOST_CHECK_EQUAL(any_cast<const int*>(&z), ip); + + any<dst_concept, const _a&> cy(as_const(x), make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<const int*>(&cy), ip); + any<dst_concept, const _a&> cz(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<const int*>(&cz), ip); +} diff --git a/src/boost/libs/type_erasure/test/test_construct_ref.cpp b/src/boost/libs/type_erasure/test/test_construct_ref.cpp new file mode 100644 index 000000000..ad2d6e46f --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_construct_ref.cpp @@ -0,0 +1,184 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/relaxed.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +template<class T> +T as_rvalue(const T& arg) { return arg; } +template<class T> +const T& as_const(const T& arg) { return arg; } + +BOOST_AUTO_TEST_CASE(test_implicit) { + int i = 4; + any<common<>, _self&> x = i; + BOOST_CHECK_EQUAL(any_cast<int*>(&x), &i); +} + +BOOST_AUTO_TEST_CASE(test_from_int_with_binding) +{ + typedef ::boost::mpl::vector<common<> > test_concept; + int i = 4; + any<test_concept, _self&> x(i, make_binding<boost::mpl::map<boost::mpl::pair<_self, int> > >()); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), &i); +} + +BOOST_AUTO_TEST_CASE(test_copy) +{ + typedef ::boost::mpl::vector<typeid_<> > test_concept; + int i = 4; + any<test_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), &i); + any<test_concept, _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), &i); + any<test_concept, _self&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&z), &i); + any<test_concept, _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_convert) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), &i); + any<dst_concept, _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), &i); + any<dst_concept, _self&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&z), &i); + any<dst_concept, _self&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind) +{ + typedef ::boost::mpl::vector<typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), &i); + any<dst_concept, _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), &i); + any<dst_concept, _a&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&z), &i); + any<dst_concept, _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), &i); + any<dst_concept, _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), &i); + any<dst_concept, _a&> z = as_rvalue(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&z), &i); + any<dst_concept, _a&> w = as_const(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&w), &i); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + binding<dst_concept> table(make_binding<types>()); + + int i = 4; + any<src_concept, _self&> x(i); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), &i); + any<dst_concept, _a&> y(x, make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), &i); + any<dst_concept, _a&> z(x, table); + BOOST_CHECK_EQUAL(any_cast<int*>(&z), &i); + + any<dst_concept, _a&> cy(as_const(x), make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<int*>(&cy), &i); + any<dst_concept, _a&> cz(as_const(x), table); + BOOST_CHECK_EQUAL(any_cast<int*>(&cz), &i); +} + +BOOST_AUTO_TEST_CASE(test_copy_from_value) +{ + typedef ::boost::mpl::vector<destructible<>, typeid_<> > test_concept; + any<test_concept> x(4); + int* ip = any_cast<int*>(&x); + any<test_concept, _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), ip); +} + +BOOST_AUTO_TEST_CASE(test_convert_from_value) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<> > dst_concept; + any<src_concept> x(4); + int* ip = any_cast<int*>(&x); + any<dst_concept, _self&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), ip); +} + +BOOST_AUTO_TEST_CASE(test_rebind_from_value) +{ + typedef ::boost::mpl::vector<destructible<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<destructible<_a>, typeid_<_a> > dst_concept; + any<src_concept> x(4); + int* ip = any_cast<int*>(&x); + any<dst_concept, _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), ip); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_from_value) +{ + typedef ::boost::mpl::vector<common<>, typeid_<> > src_concept; + typedef ::boost::mpl::vector<typeid_<_a> > dst_concept; + any<src_concept> x(4); + int* ip = any_cast<int*>(&x); + any<dst_concept, _a&> y(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), ip); +} + +BOOST_AUTO_TEST_CASE(test_rebind_and_convert_with_binding_from_value) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > src_concept; + typedef ::boost::mpl::vector<common<_a> > dst_concept; + typedef ::boost::mpl::map<boost::mpl::pair<_a, _self> > map; + typedef ::boost::mpl::map<boost::mpl::pair<_a, int> > types; + + binding<dst_concept> table(make_binding<types>()); + + any<src_concept> x(4); + int* ip = any_cast<int*>(&x); + any<dst_concept, _a&> y(x, make_binding<map>()); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), ip); + any<dst_concept, _a&> z(x, table); + BOOST_CHECK_EQUAL(any_cast<int*>(&z), ip); +} diff --git a/src/boost/libs/type_erasure/test/test_deduced.cpp b/src/boost/libs/type_erasure/test/test_deduced.cpp new file mode 100644 index 000000000..7e019cd4e --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_deduced.cpp @@ -0,0 +1,51 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/deduced.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/remove_pointer.hpp> +#include <boost/type_traits/is_same.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_deduce_dereference) +{ + typedef ::boost::mpl::vector< + copy_constructible<>, + typeid_<deduced<boost::remove_pointer<_self> >::type>, + dereferenceable<deduced<boost::remove_pointer<_self> >&> + > test_concept; + int i; + any<test_concept> x(&i); + any<test_concept, deduced<boost::remove_pointer<_self> >&> y(*x); + BOOST_CHECK_EQUAL(&any_cast<int&>(y), &i); +} + +BOOST_MPL_ASSERT(( + boost::is_same< + deduced<boost::remove_pointer<_self> >::type, + deduced<boost::remove_pointer<_self> > >)); + +BOOST_MPL_ASSERT(( + boost::is_same<deduced<boost::remove_pointer<int*> >::type, int >)); diff --git a/src/boost/libs/type_erasure/test/test_dereference.cpp b/src/boost/libs/type_erasure/test/test_dereference.cpp new file mode 100644 index 000000000..92ed1c87d --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_dereference.cpp @@ -0,0 +1,60 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_basic) +{ + typedef ::boost::mpl::vector<common<>, dereferenceable<int&> > test_concept; + int i; + any<test_concept> x(&i); + BOOST_CHECK_EQUAL(&*x, &i); +} + +BOOST_AUTO_TEST_CASE(test_any_result) +{ + typedef ::boost::mpl::vector<common<>, common<_a>, dereferenceable<_a&> > test_concept; + typedef ::boost::mpl::map< + ::boost::mpl::pair<_self, int*>, + ::boost::mpl::pair<_a, int> + > types; + int i; + any<test_concept> x(&i, make_binding<types>()); + any<test_concept, _a&> y(*x); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), &i); +} + +BOOST_AUTO_TEST_CASE(test_any_result_const) +{ + typedef ::boost::mpl::vector<common<>, common<_a>, dereferenceable<const _a&> > test_concept; + typedef ::boost::mpl::map< + ::boost::mpl::pair<_self, const int*>, + ::boost::mpl::pair<_a, int> + > types; + const int i = 0; + any<test_concept> x(&i, make_binding<types>()); + any<test_concept, const _a&> y(*x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i); +} diff --git a/src/boost/libs/type_erasure/test/test_dynamic_any_cast.cpp b/src/boost/libs/type_erasure/test/test_dynamic_any_cast.cpp new file mode 100644 index 000000000..42842dc1e --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_dynamic_any_cast.cpp @@ -0,0 +1,265 @@ +// Boost.TypeErasure library +// +// Copyright 2015 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/dynamic_any_cast.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/map.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +struct fixture +{ + fixture() + { + register_binding<common<>, int>(); + register_binding<incrementable<>, int>(); + register_binding<addable<_self, _self, _a> >(make_binding<boost::mpl::map<boost::mpl::pair<_self, int>, boost::mpl::pair<_a, int> > >()); + } +}; + +BOOST_GLOBAL_FIXTURE(fixture); + +BOOST_AUTO_TEST_CASE(test_identical) +{ + any<common<> > x(1); + any<common<> > y = dynamic_any_cast<any<common<> > >(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 1); +} + +BOOST_AUTO_TEST_CASE(test_downcast) +{ + any<common<> > x(1); + typedef any< ::boost::mpl::vector<common<>, incrementable<> > > incrementable_any; + incrementable_any y = dynamic_any_cast<incrementable_any>(x); + ++y; + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); +} + +BOOST_AUTO_TEST_CASE(test_cross_cast) +{ + any< ::boost::mpl::vector<common<>, decrementable<> > > x(1); + typedef any< ::boost::mpl::vector<common<>, incrementable<> > > incrementable_any; + incrementable_any y = dynamic_any_cast<incrementable_any>(x); + ++y; + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); +} + +BOOST_AUTO_TEST_CASE(test_cast_placeholder) +{ + any<common<> > x(1); + typedef any< ::boost::mpl::vector<common<_a>, incrementable<_a> >, _a> incrementable_any; + incrementable_any y = dynamic_any_cast<incrementable_any>(x); + ++y; + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); +} + +BOOST_AUTO_TEST_CASE(test_throw) +{ + any<common<> > x("42"); + typedef any< ::boost::mpl::vector<common<_a>, incrementable<_a> >, _a> incrementable_any; + BOOST_CHECK_THROW(dynamic_any_cast<incrementable_any>(x), bad_any_cast); +} + +// make sure that a function registered with _self can +// be found with _a. +BOOST_AUTO_TEST_CASE(test_other_placeholder) +{ + any<common<_a>, _a> x(1); + typedef any< ::boost::mpl::vector<common<_a>, incrementable<_a> >, _a> incrementable_any; + incrementable_any y = dynamic_any_cast<incrementable_any>(x); + ++y; + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); +} + +// Casting to a value only requires the target to provide +// a copy constructor. +BOOST_AUTO_TEST_CASE(test_add_copy) +{ + any< ::boost::mpl::vector<destructible<>, typeid_<> > > x(1); + any<common<> > y = dynamic_any_cast<any<common<> > >(x); + BOOST_CHECK_EQUAL(any_cast<int>(y), 1); +} + +template<class T, class U> +struct choose_second +{ + typedef U type; +}; + +BOOST_AUTO_TEST_CASE(test_deduced) +{ + typedef deduced<choose_second<_self, int> > _p2; + any< ::boost::mpl::vector<common<>, common<_p2> > > x(1); + typedef ::boost::mpl::vector<common<>, common<_p2>, incrementable<_p2>, addable<_self, _self, _p2> > dest_concept; + any<dest_concept> y = dynamic_any_cast<any<dest_concept> >(x); + any<dest_concept, _p2> z = y + y; + ++z; + BOOST_CHECK_EQUAL(any_cast<int>(z), 3); +} + +BOOST_AUTO_TEST_CASE(test_multiple_placeholders) +{ + typedef ::boost::mpl::map< ::boost::mpl::pair<_a, int>, boost::mpl::pair<_b, int> > init_map; + any< ::boost::mpl::vector<common<_a>, common<_b> >, _a> x(1, make_binding<init_map>()); + typedef ::boost::mpl::vector<common<_a>, common<_b>, incrementable<_b>, addable<_a, _a, _b> > dest_concept; + typedef ::boost::mpl::map< ::boost::mpl::pair<_a, _a>, ::boost::mpl::pair<_b, _b> > placeholder_map; + any<dest_concept, _a> y = dynamic_any_cast<any<dest_concept, _a> >(x, make_binding<placeholder_map>()); + any<dest_concept, _b> z = y + y; + ++z; + BOOST_CHECK_EQUAL(any_cast<int>(z), 3); +} + +BOOST_AUTO_TEST_CASE(test_multiple_placeholders_switch) +{ + typedef ::boost::mpl::map< ::boost::mpl::pair<_a, int>, boost::mpl::pair<_b, int> > init_map; + any< ::boost::mpl::vector<common<_a>, common<_b> >, _a> x(1, make_binding<init_map>()); + typedef ::boost::mpl::vector<common<_c>, common<_d>, incrementable<_d>, addable<_c, _c, _d> > dest_concept; + typedef ::boost::mpl::map< ::boost::mpl::pair<_c, _a>, ::boost::mpl::pair<_d, _b> > placeholder_map; + any<dest_concept, _c> y = dynamic_any_cast<any<dest_concept, _c> >(x, make_binding<placeholder_map>()); + any<dest_concept, _d> z = y + y; + ++z; + BOOST_CHECK_EQUAL(any_cast<int>(z), 3); +} + +template<class T> +T as_rvalue(const T& arg) { return arg; } +template<class T> +const T& as_const(const T& arg) { return arg; } + +BOOST_AUTO_TEST_CASE(test_val) +{ + any<common<> > x(1); + // value + any<common<> > y1 = dynamic_any_cast<any<common<> > >(x); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(y1)); + any<common<> > y2 = dynamic_any_cast<any<common<> > >(as_rvalue(x)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(y2)); + any<common<> > y3 = dynamic_any_cast<any<common<> > >(as_const(x)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(y3)); + + // lvalue reference + any<common<>, _self&> r(x); + any<common<> > z1 = dynamic_any_cast<any<common<> > >(r); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(z1)); + any<common<> > z2 = dynamic_any_cast<any<common<> > >(as_rvalue(r)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(z2)); + any<common<> > z3 = dynamic_any_cast<any<common<> > >(as_const(r)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(z3)); + + // const reference + any<common<>, const _self&> cr(x); + any<common<> > w1 = dynamic_any_cast<any<common<> > >(cr); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(w1)); + any<common<> > w2 = dynamic_any_cast<any<common<> > >(as_rvalue(cr)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(w2)); + any<common<> > w3 = dynamic_any_cast<any<common<> > >(as_const(cr)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(w3)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + // rvalue reference + any<common<>, _self&&> rr(std::move(x)); + any<common<> > v1 = dynamic_any_cast<any<common<> > >(rr); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(v1)); + any<common<> > v2 = dynamic_any_cast<any<common<> > >(as_rvalue(rr)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(v2)); + any<common<> > v3 = dynamic_any_cast<any<common<> > >(as_const(rr)); + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(v3)); +#endif +} + +BOOST_AUTO_TEST_CASE(test_ref) +{ + // A non-const reference can only bind to a few cases + any<common<> > x(1); + any<common<>, _self&> y = dynamic_any_cast<any<common<>, _self&> >(x); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&y)); + + any<common<>, _self&> z = dynamic_any_cast<any<common<>, _self&> >(y); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&z)); + any<common<>, _self&> w = dynamic_any_cast<any<common<>, _self&> >(as_rvalue(y)); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&w)); + any<common<>, _self&> v = dynamic_any_cast<any<common<>, _self&> >(as_const(y)); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&v)); +} + +BOOST_AUTO_TEST_CASE(test_cref) +{ + any<common<> > x(1); + typedef any<common<>, const _self&> dest_type; + + // value + dest_type y1 = dynamic_any_cast<dest_type>(x); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&y1)); + // as_rvalue creates a temporary + BOOST_CHECK_EQUAL(any_cast<int>(x), any_cast<int>(dynamic_any_cast<dest_type>(as_rvalue(x)))); + dest_type y3 = dynamic_any_cast<dest_type>(as_const(x)); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&y3)); + + // lvalue reference + any<common<>, _self&> r(x); + dest_type z1 = dynamic_any_cast<dest_type>(r); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&z1)); + dest_type z2 = dynamic_any_cast<dest_type>(as_rvalue(r)); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&z2)); + dest_type z3 = dynamic_any_cast<dest_type>(as_const(r)); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&z3)); + + // const reference + any<common<>, const _self&> cr(x); + dest_type w1 = dynamic_any_cast<dest_type>(cr); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&w1)); + dest_type w2 = dynamic_any_cast<dest_type>(as_rvalue(cr)); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&w2)); + dest_type w3 = dynamic_any_cast<dest_type>(as_const(cr)); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&w3)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + // rvalue reference + any<common<>, _self&&> rr(std::move(x)); + dest_type v1 = dynamic_any_cast<dest_type>(rr); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&v1)); + dest_type v2 = dynamic_any_cast<dest_type>(as_rvalue(rr)); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&v2)); + dest_type v3 = dynamic_any_cast<dest_type>(as_const(rr)); + BOOST_CHECK_EQUAL(any_cast<const int*>(&x), any_cast<const int*>(&v3)); +#endif +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +BOOST_AUTO_TEST_CASE(test_rref) +{ + any<common<> > x(1); + typedef any<common<>, _self&&> dest_type; + + // value + dest_type y2 = dynamic_any_cast<dest_type>(std::move(x)); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&y2)); + + // rvalue reference + any<common<>, _self&&> rr(std::move(x)); + dest_type v2 = dynamic_any_cast<dest_type>(std::move(rr)); + BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&v2)); +} + +#endif diff --git a/src/boost/libs/type_erasure/test/test_equal.cpp b/src/boost/libs/type_erasure/test/test_equal.cpp new file mode 100644 index 000000000..e0989cd13 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_equal.cpp @@ -0,0 +1,147 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_AUTO_TEST_CASE(test_basic) +{ + typedef boost::mpl::vector<copy_constructible<>, equality_comparable<> > test_concept; + any<test_concept> x(1); + any<test_concept> y(2); + + BOOST_CHECK(!(x == y)); + BOOST_CHECK((x == x)); + BOOST_CHECK((x != y)); + BOOST_CHECK(!(x != x)); +} + +BOOST_AUTO_TEST_CASE(test_mixed_unequal) +{ + typedef boost::mpl::vector<copy_constructible<_a>, copy_constructible<_b>, equality_comparable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> t(1, 2.0); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + BOOST_CHECK(!(x == y)); + BOOST_CHECK((x != y)); +} + +BOOST_AUTO_TEST_CASE(test_mixed_equal) +{ + typedef boost::mpl::vector<copy_constructible<_a>, copy_constructible<_b>, equality_comparable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> t(1, 1); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + BOOST_CHECK((x == y)); + BOOST_CHECK(!(x != y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_lhs_unequal) +{ + typedef boost::mpl::vector<copy_constructible<>, equality_comparable<int, _self> > test_concept; + int x(1); + any<test_concept> y(2.0); + + BOOST_CHECK(!(x == y)); + BOOST_CHECK((x != y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_lhs_equal) +{ + typedef boost::mpl::vector<copy_constructible<>, equality_comparable<int, _self> > test_concept; + int x(1); + any<test_concept> y(1); + + BOOST_CHECK((x == y)); + BOOST_CHECK(!(x != y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_rhs_unequal) +{ + typedef boost::mpl::vector<copy_constructible<>, equality_comparable<_self, int> > test_concept; + any<test_concept> x(2.0); + int y(1); + + BOOST_CHECK(!(x == y)); + BOOST_CHECK((x != y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_rhs_equal) +{ + typedef boost::mpl::vector<copy_constructible<>, equality_comparable<_self, int> > test_concept; + any<test_concept> x(1); + int y(1); + + BOOST_CHECK((x == y)); + BOOST_CHECK(!(x != y)); +} + +BOOST_AUTO_TEST_CASE(test_relaxed) +{ + typedef boost::mpl::vector<copy_constructible<>, equality_comparable<>, relaxed> test_concept; + any<test_concept> x(1); + any<test_concept> y(2); + any<test_concept> z(std::string("test")); + + BOOST_CHECK(!(x == y)); + BOOST_CHECK((x == x)); + BOOST_CHECK((x != y)); + BOOST_CHECK(!(x != x)); + + BOOST_CHECK(!(x == z)); + BOOST_CHECK((x != z)); +} + +BOOST_AUTO_TEST_CASE(test_overload) +{ + typedef boost::mpl::vector< + copy_constructible<_a>, + copy_constructible<_b>, + equality_comparable<_a>, + equality_comparable<_a, int>, + equality_comparable<int, _a>, + equality_comparable<_b>, + equality_comparable<_b, int>, + equality_comparable<int, _b>, + equality_comparable<_a, _b> + > test_concept; + + tuple<test_concept, _a, _b> t(1, 2.0); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + BOOST_CHECK(x == x); + BOOST_CHECK(!(x != x)); + BOOST_CHECK(x == 1); + BOOST_CHECK(x != 2); + BOOST_CHECK(1 == x); + BOOST_CHECK(2 != x); + + BOOST_CHECK(y == y); + BOOST_CHECK(!(y != y)); + BOOST_CHECK(y == 2); + BOOST_CHECK(y != 3); + BOOST_CHECK(2 == y); + BOOST_CHECK(3 != y); + + BOOST_CHECK(!(x == y)); + BOOST_CHECK(x != y); +} diff --git a/src/boost/libs/type_erasure/test/test_forward_iterator.cpp b/src/boost/libs/type_erasure/test/test_forward_iterator.cpp new file mode 100644 index 000000000..159cffb07 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_forward_iterator.cpp @@ -0,0 +1,99 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/iterator.hpp> +#include <boost/type_erasure/same_type.hpp> +#include <boost/type_erasure/binding_of.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/concept_check.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_AUTO_TEST_CASE(test_basic) +{ + typedef boost::mpl::vector< + forward_iterator<>, + same_type<forward_iterator<>::value_type, int> + > test_concept; + std::vector<int> vec(10); + any<test_concept> x(vec.begin()); + any<test_concept> y(vec.end()); + + for(int i = 0; x != y; ++x, ++i) { + *x = i; + } + int expected[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), &expected[0], &expected[0] + 10); + + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::value_type, int>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::reference, int&>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::pointer, int*>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::difference_type, std::ptrdiff_t>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::iterator_category, std::forward_iterator_tag>)); +} + +BOOST_AUTO_TEST_CASE(test_any_value_type) +{ + typedef boost::mpl::vector< + forward_iterator<>, + same_type<forward_iterator<>::value_type, _a>, + copy_constructible<_a>, + assignable<_a>, + incrementable<_a> + > test_concept; + std::vector<int> vec(10); + any<test_concept> x(vec.begin()); + any<test_concept> y(vec.end()); + + for(any<test_concept, _a> i = *x; x != y; ++x, ++i) { + *x = i; + } + int expected[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), &expected[0], &expected[0] + 10); + + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::value_type, any<test_concept, _a> >)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::reference, any<test_concept, _a&> >)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::pointer, any<test_concept, _a>*>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::difference_type, std::ptrdiff_t>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::iterator_category, std::forward_iterator_tag>)); +} + +BOOST_AUTO_TEST_CASE(test_relaxed) +{ + typedef boost::mpl::vector< + forward_iterator<>, + same_type<forward_iterator<>::value_type, int>, + relaxed + > test_concept; + std::vector<int> vec(10); + any<test_concept> x(vec.begin()); + any<test_concept> y(vec.end()); + + for(int i = 0; x != y; ++x, ++i) { + *x = i; + } + int expected[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + BOOST_CHECK_EQUAL_COLLECTIONS(vec.begin(), vec.end(), &expected[0], &expected[0] + 10); + + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::value_type, int>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::reference, int&>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::pointer, int*>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::difference_type, std::ptrdiff_t>)); + BOOST_MPL_ASSERT((boost::is_same<any<test_concept>::iterator_category, std::forward_iterator_tag>)); + + BOOST_CONCEPT_ASSERT((boost::ForwardIterator<any<test_concept> >)); +} diff --git a/src/boost/libs/type_erasure/test/test_free.cpp b/src/boost/libs/type_erasure/test/test_free.cpp new file mode 100644 index 000000000..20e4119f0 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_free.cpp @@ -0,0 +1,146 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/free.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +struct model { + explicit model(int v) : val(v) {} + int val; +}; + +int f1(model& m) { return m.val; } +int f1(model& m, int i) { return m.val + i; } + +BOOST_TYPE_ERASURE_FREE((global_has_f1_1), f1, 1) + +BOOST_AUTO_TEST_CASE(test_global_has_f1_1) { + typedef ::boost::mpl::vector< + global_has_f1_1<int(_self&)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(x), 10); +} + +BOOST_TYPE_ERASURE_FREE((ns1)(ns2)(ns_has_f1_1), f1, 1) + +BOOST_AUTO_TEST_CASE(test_ns_has_f1_1) { + typedef ::boost::mpl::vector< + ns1::ns2::ns_has_f1_1<int(_self&)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(x), 10); +} + +struct model_const { + explicit model_const(int v) : val(v) {} + int val; +}; + +int f1(const model_const& m) { return m.val; } +int f1(const model_const& m, int i) { return m.val + i; } + +BOOST_AUTO_TEST_CASE(test_global_has_f1_1_const) { + typedef ::boost::mpl::vector< + ns1::ns2::ns_has_f1_1<int(const _self&)>, + copy_constructible<> > concept_type; + model_const m(10); + const any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(x), 10); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_1_void) { + typedef ::boost::mpl::vector< + global_has_f1_1<void(_self&)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + f1(x); +} + +BOOST_TYPE_ERASURE_FREE((global_has_f1_2), f1, 2) + +BOOST_AUTO_TEST_CASE(test_global_has_f1_overload) { + typedef ::boost::mpl::vector< + global_has_f1_1<int(_self&)>, + global_has_f1_2<int(_self&, int)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(x), 10); + BOOST_CHECK_EQUAL(f1(x, 5), 15); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_overload_const) { + typedef ::boost::mpl::vector< + global_has_f1_1<int(const _self&)>, + global_has_f1_2<int(const _self&, int)>, + copy_constructible<> > concept_type; + model_const m(10); + const any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(x), 10); + BOOST_CHECK_EQUAL(f1(x, 5), 15); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +BOOST_AUTO_TEST_CASE(test_global_has_f1_rv) { + typedef ::boost::mpl::vector< + global_has_f1_2<int(_self&&, int&&)>, + copy_constructible<> > concept_type; + model_const m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(std::move(x), 5), 15); +} + +#endif + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_DECLTYPE) && \ + !BOOST_WORKAROUND(BOOST_MSVC, == 1800) + +namespace ns3 { +BOOST_TYPE_ERASURE_FREE(f1) +} + +BOOST_AUTO_TEST_CASE(test_simple_free_1) { + typedef ::boost::mpl::vector< + ns3::has_f1<int(_self&)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(x), 10); +} + +namespace ns3 { +BOOST_TYPE_ERASURE_FREE(has_f1_ex, f1) +} + +BOOST_AUTO_TEST_CASE(test_named_free_1) { + typedef ::boost::mpl::vector< + ns3::has_f1_ex<int(_self&)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(f1(x), 10); +} + +#endif diff --git a/src/boost/libs/type_erasure/test/test_increment.cpp b/src/boost/libs/type_erasure/test/test_increment.cpp new file mode 100644 index 000000000..f864dfaf3 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_increment.cpp @@ -0,0 +1,51 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + destructible<T>, + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_value) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > test_concept; + any<test_concept> x(1); + ++x; + BOOST_CHECK_EQUAL(any_cast<int>(x), 2); + any<test_concept> y(x++); + BOOST_CHECK_EQUAL(any_cast<int>(x), 3); + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); +} + +BOOST_AUTO_TEST_CASE(test_reference) +{ + typedef ::boost::mpl::vector<common<>, incrementable<> > test_concept; + int i = 1; + any<test_concept, _self&> x(i); + ++x; + BOOST_CHECK_EQUAL(i, 2); + any<test_concept> y(x++); + BOOST_CHECK_EQUAL(i, 3); + BOOST_CHECK_EQUAL(any_cast<int>(y), 2); +} diff --git a/src/boost/libs/type_erasure/test/test_interface_order.cpp b/src/boost/libs/type_erasure/test/test_interface_order.cpp new file mode 100644 index 000000000..60127353e --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_interface_order.cpp @@ -0,0 +1,51 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> + +using namespace boost::type_erasure; +namespace mpl = boost::mpl; + +template<class T = _self> +struct common : mpl::vector< + copy_constructible<T> +> {}; + +template<class T = _self> +struct concept1 : mpl::vector<copy_constructible<T> > {}; + +template<class T = _self> +struct concept2 : mpl::vector<concept1<T> > {}; + +namespace boost { +namespace type_erasure { + +template<class T, class Base> +struct concept_interface<concept1<T>, Base, T> : Base +{ + typedef int id_type; +}; + +template<class T, class Base> +struct concept_interface<concept2<T>, Base, T> : Base +{ + typedef char id_type; +}; + +} +} + +BOOST_MPL_ASSERT((boost::is_same<any<concept2<> >::id_type, char>)); +BOOST_MPL_ASSERT((boost::is_same<any<mpl::vector<concept2<>, concept1<> > >::id_type, char>)); +BOOST_MPL_ASSERT((boost::is_same<any<mpl::vector<concept1<>, concept2<> > >::id_type, char>)); diff --git a/src/boost/libs/type_erasure/test/test_is_empty.cpp b/src/boost/libs/type_erasure/test/test_is_empty.cpp new file mode 100644 index 000000000..bb416c66f --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_is_empty.cpp @@ -0,0 +1,35 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/is_empty.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_AUTO_TEST_CASE(test_non_relaxed) +{ + typedef copy_constructible<> test_concept; + any<test_concept> x(2); + BOOST_CHECK(!is_empty(x)); +} + +BOOST_AUTO_TEST_CASE(test_relaxed) +{ + typedef boost::mpl::vector<copy_constructible<>, relaxed> test_concept; + any<test_concept> x(2); + BOOST_CHECK(!is_empty(x)); + any<test_concept> y; + BOOST_CHECK(is_empty(y)); +} diff --git a/src/boost/libs/type_erasure/test/test_is_placeholder.cpp b/src/boost/libs/type_erasure/test/test_is_placeholder.cpp new file mode 100644 index 000000000..b171f03d3 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_is_placeholder.cpp @@ -0,0 +1,33 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/is_placeholder.hpp> +#include <boost/type_erasure/placeholder.hpp> +#include <boost/mpl/assert.hpp> + +using namespace boost::type_erasure; + +struct a_placeholder : placeholder {}; +struct not_placeholder {}; +struct incomplete; + +template<class T> +struct t_placeholder : placeholder {}; + +template<class T> +struct t_incomplete; + +BOOST_MPL_ASSERT((is_placeholder<a_placeholder>)); +BOOST_MPL_ASSERT_NOT((is_placeholder<not_placeholder>)); +BOOST_MPL_ASSERT_NOT((is_placeholder<incomplete>)); +BOOST_MPL_ASSERT_NOT((is_placeholder<int>)); +BOOST_MPL_ASSERT_NOT((is_placeholder<void>)); +BOOST_MPL_ASSERT((is_placeholder<t_placeholder<int> >)); +BOOST_MPL_ASSERT_NOT((is_placeholder<t_incomplete<int> >)); diff --git a/src/boost/libs/type_erasure/test/test_is_subconcept.cpp b/src/boost/libs/type_erasure/test/test_is_subconcept.cpp new file mode 100644 index 000000000..995779410 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_is_subconcept.cpp @@ -0,0 +1,34 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/is_subconcept.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/assert.hpp> + +namespace mpl = boost::mpl; +using namespace boost::type_erasure; + +BOOST_MPL_ASSERT((is_subconcept<typeid_<>, typeid_<> >)); +BOOST_MPL_ASSERT_NOT((is_subconcept<typeid_<>, incrementable<> >)); +BOOST_MPL_ASSERT_NOT((is_subconcept<mpl::vector<typeid_<>, incrementable<> >, typeid_<> >)); +BOOST_MPL_ASSERT_NOT((is_subconcept<mpl::vector<typeid_<>, incrementable<> >, incrementable<> >)); +BOOST_MPL_ASSERT((is_subconcept<typeid_<>, mpl::vector<typeid_<>, incrementable<> > >)); +BOOST_MPL_ASSERT((is_subconcept<incrementable<>, mpl::vector<typeid_<>, incrementable<> > >)); +BOOST_MPL_ASSERT((is_subconcept<mpl::vector<typeid_<>, incrementable<> >, mpl::vector<incrementable<>, typeid_<> > >)); + +BOOST_MPL_ASSERT((is_subconcept<typeid_<_a>, typeid_<_b>, mpl::map<mpl::pair<_a, _b> > >)); +BOOST_MPL_ASSERT_NOT((is_subconcept<typeid_<_a>, incrementable<_b>, mpl::map<mpl::pair<_a, _b> > >)); +BOOST_MPL_ASSERT_NOT((is_subconcept<mpl::vector<typeid_<_a>, incrementable<_a> >, typeid_<_b>, mpl::map<mpl::pair<_a, _b> > >)); +BOOST_MPL_ASSERT_NOT((is_subconcept<mpl::vector<typeid_<_a>, incrementable<_a> >, incrementable<_b>, mpl::map<mpl::pair<_a, _b> > >)); +BOOST_MPL_ASSERT((is_subconcept<typeid_<_a>, mpl::vector<typeid_<_b>, incrementable<_b> >, mpl::map<mpl::pair<_a, _b> > >)); +BOOST_MPL_ASSERT((is_subconcept<incrementable<_a>, mpl::vector<typeid_<_b>, incrementable<_b> >, mpl::map<mpl::pair<_a, _b> > >)); +BOOST_MPL_ASSERT((is_subconcept<mpl::vector<typeid_<_a>, incrementable<_a> >, mpl::vector<incrementable<_b>, typeid_<_b> >, mpl::map<mpl::pair<_a, _b> > >)); diff --git a/src/boost/libs/type_erasure/test/test_less.cpp b/src/boost/libs/type_erasure/test/test_less.cpp new file mode 100644 index 000000000..343bb51ad --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_less.cpp @@ -0,0 +1,260 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_AUTO_TEST_CASE(test_basic) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<> > test_concept; + any<test_concept> x(1); + any<test_concept> y(2); + + BOOST_CHECK((x < y)); + BOOST_CHECK(!(y < x)); + BOOST_CHECK(!(x < x)); + + BOOST_CHECK(!(x > y)); + BOOST_CHECK((y > x)); + BOOST_CHECK(!(x > x)); + + BOOST_CHECK((x <= y)); + BOOST_CHECK(!(y <= x)); + BOOST_CHECK((x <= x)); + + BOOST_CHECK(!(x >= y)); + BOOST_CHECK((y >= x)); + BOOST_CHECK((x >= x)); +} + +BOOST_AUTO_TEST_CASE(test_mixed_less) +{ + typedef boost::mpl::vector<copy_constructible<_a>, copy_constructible<_b>, less_than_comparable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> t(1, 2.0); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + BOOST_CHECK((x < y)); + BOOST_CHECK((y > x)); + BOOST_CHECK(!(y <= x)); + BOOST_CHECK(!(x >= y)); +} + +BOOST_AUTO_TEST_CASE(test_mixed_equal) +{ + typedef boost::mpl::vector<copy_constructible<_a>, copy_constructible<_b>, less_than_comparable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> t(1, 1); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + BOOST_CHECK(!(x < y)); + BOOST_CHECK(!(y > x)); + BOOST_CHECK((y <= x)); + BOOST_CHECK((x >= y)); +} + +BOOST_AUTO_TEST_CASE(test_mixed_greater) +{ + typedef boost::mpl::vector<copy_constructible<_a>, copy_constructible<_b>, less_than_comparable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> t(2.0, 1); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + BOOST_CHECK(!(x < y)); + BOOST_CHECK(!(y > x)); + BOOST_CHECK((y <= x)); + BOOST_CHECK((x >= y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_lhs_less) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<int, _self> > test_concept; + int x(1); + any<test_concept> y(2.0); + + BOOST_CHECK((x < y)); + BOOST_CHECK((y > x)); + BOOST_CHECK(!(y <= x)); + BOOST_CHECK(!(x >= y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_lhs_equal) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<int, _self> > test_concept; + int x(1); + any<test_concept> y(1); + + BOOST_CHECK(!(x < y)); + BOOST_CHECK(!(y > x)); + BOOST_CHECK((y <= x)); + BOOST_CHECK((x >= y)); +} + + +BOOST_AUTO_TEST_CASE(test_fixed_lhs_greater) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<int, _self> > test_concept; + int x(1); + any<test_concept> y(0.5); + + BOOST_CHECK(!(x < y)); + BOOST_CHECK(!(y > x)); + BOOST_CHECK((y <= x)); + BOOST_CHECK((x >= y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_rhs_less) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<_self, int> > test_concept; + any<test_concept> x(1.0); + int y(2); + + BOOST_CHECK((x < y)); + BOOST_CHECK((y > x)); + BOOST_CHECK(!(y <= x)); + BOOST_CHECK(!(x >= y)); +} + +BOOST_AUTO_TEST_CASE(test_fixed_rhs_equal) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<_self, int> > test_concept; + any<test_concept> x(1); + int y(1); + + BOOST_CHECK(!(x < y)); + BOOST_CHECK(!(y > x)); + BOOST_CHECK((y <= x)); + BOOST_CHECK((x >= y)); +} + + +BOOST_AUTO_TEST_CASE(test_fixed_rhs_greater) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<_self, int> > test_concept; + any<test_concept> x(2.0); + int y(1); + + BOOST_CHECK(!(x < y)); + BOOST_CHECK(!(y > x)); + BOOST_CHECK((y <= x)); + BOOST_CHECK((x >= y)); +} + +BOOST_AUTO_TEST_CASE(test_relaxed) +{ + typedef boost::mpl::vector<copy_constructible<>, less_than_comparable<>, relaxed> test_concept; + any<test_concept> x(1); + any<test_concept> y(2); + any<test_concept> z(std::string("test")); + + BOOST_CHECK((x < y)); + BOOST_CHECK(!(y < x)); + BOOST_CHECK(!(x < x)); + + BOOST_CHECK(!(x > y)); + BOOST_CHECK((y > x)); + BOOST_CHECK(!(x > x)); + + BOOST_CHECK((x <= y)); + BOOST_CHECK(!(y <= x)); + BOOST_CHECK((x <= x)); + + BOOST_CHECK(!(x >= y)); + BOOST_CHECK((y >= x)); + BOOST_CHECK((x >= x)); + + bool expected = x < z; + + BOOST_CHECK_EQUAL((x < z), expected); + BOOST_CHECK_EQUAL(!(z < x), expected); + + BOOST_CHECK_EQUAL(!(x > z), expected); + BOOST_CHECK_EQUAL((z > x), expected); + + BOOST_CHECK_EQUAL((x <= z), expected); + BOOST_CHECK_EQUAL(!(z <= x), expected); + + BOOST_CHECK_EQUAL(!(x >= z), expected); + BOOST_CHECK_EQUAL((z >= x), expected); + + BOOST_CHECK_EQUAL((y < z), expected); + BOOST_CHECK_EQUAL(!(z < y), expected); + + BOOST_CHECK_EQUAL(!(y > z), expected); + BOOST_CHECK_EQUAL((z > y), expected); + + BOOST_CHECK_EQUAL((y <= z), expected); + BOOST_CHECK_EQUAL(!(z <= y), expected); + + BOOST_CHECK_EQUAL(!(y >= z), expected); + BOOST_CHECK_EQUAL((z >= y), expected); +} + +BOOST_AUTO_TEST_CASE(test_overload) +{ + typedef boost::mpl::vector< + copy_constructible<_a>, + copy_constructible<_b>, + less_than_comparable<_a>, + less_than_comparable<_a, int>, + less_than_comparable<int, _a>, + less_than_comparable<_b>, + less_than_comparable<_b, int>, + less_than_comparable<int, _b>, + less_than_comparable<_a, _b> + > test_concept; + tuple<test_concept, _a, _b> t(1, 2); + any<test_concept, _a> x(get<0>(t)); + any<test_concept, _b> y(get<1>(t)); + + BOOST_CHECK(!(x < x)); + BOOST_CHECK(x <= x); + BOOST_CHECK(!(x > x)); + BOOST_CHECK(x >= x); + + BOOST_CHECK(!(x < 1)); + BOOST_CHECK(x <= 1); + BOOST_CHECK(!(x > 1)); + BOOST_CHECK(x >= 1); + + BOOST_CHECK(!(1 < x)); + BOOST_CHECK(1 <= x); + BOOST_CHECK(!(1 > x)); + BOOST_CHECK(1 >= x); + + BOOST_CHECK(!(y < y)); + BOOST_CHECK(y <= y); + BOOST_CHECK(!(y > y)); + BOOST_CHECK(y >= y); + + BOOST_CHECK(!(y < 2)); + BOOST_CHECK(y <= 2); + BOOST_CHECK(!(y > 2)); + BOOST_CHECK(y >= 2); + + BOOST_CHECK(!(2 < y)); + BOOST_CHECK(2 <= y); + BOOST_CHECK(!(2 > y)); + BOOST_CHECK(2 >= y); + + BOOST_CHECK(x < y); + BOOST_CHECK(y > x); + BOOST_CHECK(!(y <= x)); + BOOST_CHECK(!(x >= y)); +} diff --git a/src/boost/libs/type_erasure/test/test_limits.cpp b/src/boost/libs/type_erasure/test/test_limits.cpp new file mode 100644 index 000000000..4bbf68da0 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_limits.cpp @@ -0,0 +1,94 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/free.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/transform.hpp> +#include <boost/mpl/back_inserter.hpp> +#include <boost/mpl/range_c.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; +namespace mpl = boost::mpl; + +template<int N> +struct tester +{ + int value; +}; + +int func() { return 0; } + +template<int N, class... T> +int func(tester<N> t0, T... t) +{ + return t0.value + func(t...); +} + +BOOST_TYPE_ERASURE_FREE((has_func), func) + +template<class T = _self> +struct common : mpl::vector< + copy_constructible<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_arity) +{ + tester<0> t = { 1 }; + any<mpl::vector<common<>, has_func<int(_self, _self, _self, _self, _self, _self)> > > x(t); + int i = func(x, x, x, x, x, x); + BOOST_TEST(i == 6); +} + +BOOST_AUTO_TEST_CASE(test_null_arity) +{ + any<mpl::vector<common<>, has_func<int(_self, _self, _self, _self, _self, _self)>, relaxed> > x; + BOOST_CHECK_THROW(func(x, x, x, x, x , x), boost::type_erasure::bad_function_call); +} + +template<class T0, class... T> +struct my_concept +{ + static int apply(T0 t0) { return func(t0); } +}; + +BOOST_AUTO_TEST_CASE(test_template_arity) +{ + typedef my_concept<_self, int, int, int, int, int, int> concept1; + tester<0> t = { 1 }; + any<mpl::vector<common<>, concept1> > x(t); + int i = call(concept1(), x); + BOOST_TEST(i == 1); +} + +template<class T> +struct make_funcN +{ + typedef has_func<int(_self, tester<T::value>)> type; +}; + +BOOST_AUTO_TEST_CASE(test_vtable_size) +{ + tester<0> t = { 1 }; + any<mpl::vector< + common<>, + mpl::transform<mpl::range_c<int, 1, 60>, + make_funcN<mpl::_1>, + mpl::back_inserter< boost::mp11::mp_list<> > + >::type + > > x(t); + tester<7> t1 = { 2 }; + int i = func(x, t1); + BOOST_TEST(i == 3); +} diff --git a/src/boost/libs/type_erasure/test/test_member.cpp b/src/boost/libs/type_erasure/test/test_member.cpp new file mode 100644 index 000000000..a2ebaafdd --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_member.cpp @@ -0,0 +1,242 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/member.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_TYPE_ERASURE_MEMBER((ns)(ns2)(has_fun), fun, 0) + +struct model { + explicit model(int v) : val(v) {} + int f1() { return val; } + int f1(int i) { return val + i; } + int val; +}; + +BOOST_TYPE_ERASURE_MEMBER((global_has_f1_0), f1, 0) + +BOOST_AUTO_TEST_CASE(test_global_has_f1_0) { + typedef ::boost::mpl::vector< + global_has_f1_0<int()>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_0_ref) { + typedef ::boost::mpl::vector< + global_has_f1_0<int()>, + copy_constructible<> > concept_type; + model m(10); + const any<concept_type, _self&> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); +} + +BOOST_TYPE_ERASURE_MEMBER((ns1)(ns2)(ns_has_f1_0), f1, 0) + +BOOST_AUTO_TEST_CASE(test_ns_has_f1_0) { + typedef ::boost::mpl::vector< + ns1::ns2::ns_has_f1_0<int()>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); +} + +struct model_const { + explicit model_const(int v) : val(v) {} + int f1() const { return val; } + int f1(int i) const { return val + i; } + int val; +}; + +BOOST_AUTO_TEST_CASE(test_global_has_f1_0_const) { + typedef ::boost::mpl::vector< + ns1::ns2::ns_has_f1_0<int(), const _self>, + copy_constructible<> > concept_type; + model_const m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_0_const_ref) { + typedef ::boost::mpl::vector< + ns1::ns2::ns_has_f1_0<int(), const _self>, + copy_constructible<> > concept_type; + model_const m(10); + const any<concept_type, _self&> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_0_const_cref) { + typedef ::boost::mpl::vector< + ns1::ns2::ns_has_f1_0<int(), const _self>, + copy_constructible<> > concept_type; + model_const m(10); + const any<concept_type, const _self&> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_0_void) { + typedef ::boost::mpl::vector< + global_has_f1_0<void()>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + x.f1(); +} + +BOOST_TYPE_ERASURE_MEMBER((global_has_f1_1), f1, 1) + +BOOST_AUTO_TEST_CASE(test_global_has_f1_overload) { + typedef ::boost::mpl::vector< + global_has_f1_0<int()>, + global_has_f1_1<int(int)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); + BOOST_CHECK_EQUAL(x.f1(5), 15); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_overload_const) { + typedef ::boost::mpl::vector< + global_has_f1_0<int(), const _self>, + global_has_f1_1<int(int), const _self>, + copy_constructible<> > concept_type; + model_const m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); + BOOST_CHECK_EQUAL(x.f1(5), 15); +} + +struct model_overload_const_non_const { + int f1() { return 1; } + int f1() const { return 2; } +}; + +BOOST_AUTO_TEST_CASE(test_global_has_f1_overload_const_non_const) { + typedef ::boost::mpl::vector< + global_has_f1_0<int(), _self>, + global_has_f1_0<int(), const _self>, + copy_constructible<> > concept_type; + model_overload_const_non_const m; + any<concept_type> x1(m); + BOOST_CHECK_EQUAL(x1.f1(), 1); + const any<concept_type> x2(m); + BOOST_CHECK_EQUAL(x2.f1(), 2); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_overload_const_non_const_ref) { + typedef ::boost::mpl::vector< + global_has_f1_0<int(), const _self>, // FIXME: This is order sensitive + global_has_f1_0<int(), _self>, + copy_constructible<> > concept_type; + model_overload_const_non_const m; + any<concept_type, _self&> x1(m); + BOOST_CHECK_EQUAL(x1.f1(), 1); + const any<concept_type, _self&> x2(m); + BOOST_CHECK_EQUAL(x2.f1(), 1); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_overload_const_non_const_cref) { + typedef ::boost::mpl::vector< + global_has_f1_0<int(), _self>, + global_has_f1_0<int(), const _self>, + copy_constructible<> > concept_type; + model_overload_const_non_const m; + any<concept_type, const _self&> x1(m); + BOOST_CHECK_EQUAL(x1.f1(), 2); + const any<concept_type, const _self&> x2(m); + BOOST_CHECK_EQUAL(x2.f1(), 2); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +BOOST_AUTO_TEST_CASE(test_global_has_f1_rv) { + typedef ::boost::mpl::vector< + global_has_f1_1<int(int&&)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(5), 15); +} + +BOOST_AUTO_TEST_CASE(test_global_has_f1_rv_const) { + typedef ::boost::mpl::vector< + global_has_f1_1<int(int&&), const _self>, + copy_constructible<> > concept_type; + model_const m(10); + const any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(5), 15); +} + +#endif + + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_DECLTYPE) && \ + !BOOST_WORKAROUND(BOOST_MSVC, == 1800) + +namespace ns3 { +BOOST_TYPE_ERASURE_MEMBER(f1); +} + +BOOST_AUTO_TEST_CASE(test_simple_member_0) { + typedef ::boost::mpl::vector< + ns3::has_f1<int()>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(), 10); +} + +BOOST_AUTO_TEST_CASE(test_simple_member_1) { + typedef ::boost::mpl::vector< + ns3::has_f1<int(int)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(5), 15); +} + +namespace ns3 { +BOOST_TYPE_ERASURE_MEMBER(has_f1_ex, f1); +} + +BOOST_AUTO_TEST_CASE(test_named_member_1) { + typedef ::boost::mpl::vector< + ns3::has_f1_ex<int(int)>, + copy_constructible<> > concept_type; + model m(10); + any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(5), 15); +} + +BOOST_AUTO_TEST_CASE(test_named_member_1_const) { + typedef ::boost::mpl::vector< + ns3::has_f1_ex<int(int) const>, + copy_constructible<> > concept_type; + model_const m(10); + const any<concept_type> x(m); + BOOST_CHECK_EQUAL(x.f1(5), 15); +} + +#endif diff --git a/src/boost/libs/type_erasure/test/test_negate.cpp b/src/boost/libs/type_erasure/test/test_negate.cpp new file mode 100644 index 000000000..fc35681f3 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_negate.cpp @@ -0,0 +1,34 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_negate) +{ + typedef ::boost::mpl::vector<common<>, negatable<> > test_concept; + any<test_concept> x(1); + any<test_concept> y(-x); + BOOST_CHECK_EQUAL(any_cast<int>(y), -1); +} diff --git a/src/boost/libs/type_erasure/test/test_nested.cpp b/src/boost/libs/type_erasure/test/test_nested.cpp new file mode 100644 index 000000000..5eca488e0 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_nested.cpp @@ -0,0 +1,62 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +typedef any<boost::mpl::vector<common<> > > any1_type; + +struct test_class +{ + int i; +}; + +test_class operator+(const test_class& lhs, const any1_type& rhs) +{ + test_class result = { lhs.i + any_cast<int>(rhs) }; + return result; +} + +BOOST_AUTO_TEST_CASE(test_basic) +{ + typedef boost::mpl::vector<common<>, addable<_self, any1_type> > test_concept; + any1_type a1(1); + test_class v = { 2 }; + any<test_concept> x(v); + any<test_concept> y(x + a1); + BOOST_CHECK_EQUAL(any_cast<test_class>(y).i, 3); +} + +BOOST_AUTO_TEST_CASE(test_relaxed) +{ + typedef boost::mpl::vector<common<_a>, addable<_a, any1_type>, relaxed> test_concept; + typedef boost::mpl::vector<common<_b>, addable<_b, any1_type>, relaxed> dest_concept; + any1_type a1(1); + test_class v = { 2 }; + any<test_concept, _a> x(v); + any<test_concept, _a> y(x + a1); + BOOST_CHECK_EQUAL(any_cast<test_class>(y).i, 3); + + any<dest_concept, _b> z(x); +} diff --git a/src/boost/libs/type_erasure/test/test_null.cpp b/src/boost/libs/type_erasure/test/test_null.cpp new file mode 100644 index 000000000..166f4dd6a --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_null.cpp @@ -0,0 +1,44 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + relaxed +> {}; + +BOOST_AUTO_TEST_CASE(test_typeid) { + any<common<> > val; + BOOST_CHECK(typeid_of(val) == typeid(void)); +} + +BOOST_AUTO_TEST_CASE(test_any_cast) { + any<common<> > val; + BOOST_CHECK_EQUAL(any_cast<void*>(&val), (void*)0); + BOOST_CHECK_EQUAL(any_cast<int*>(&val), (int*)0); +} + +BOOST_AUTO_TEST_CASE(test_copy) { + any<common<> > val; + any<common<> > val2(val); + BOOST_CHECK(typeid_of(val2) == typeid(void)); +} diff --git a/src/boost/libs/type_erasure/test/test_param.cpp b/src/boost/libs/type_erasure/test/test_param.cpp new file mode 100644 index 000000000..a96204107 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_param.cpp @@ -0,0 +1,251 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/param.hpp> +#include <boost/type_erasure/builtin.hpp> + +using namespace boost::type_erasure; + +template<int N> +struct size { typedef char (&type)[N]; }; + +// lvalues +extern any<copy_constructible<>, _self> a1; +extern const any<copy_constructible<>, _self> a2; +extern any<copy_constructible<>, _self&> a3; +extern const any<copy_constructible<>, _self&> a4; +extern any<copy_constructible<>, const _self&> a5; +extern const any<copy_constructible<>, const _self&> a6; + +// rvalues +any<copy_constructible<>, _self> a7(); +const any<copy_constructible<>, _self> a8(); +any<copy_constructible<>, _self&> a9(); +const any<copy_constructible<>, _self&> a10(); +any<copy_constructible<>, const _self&> a11(); +const any<copy_constructible<>, const _self&> a12(); + +extern int i; + +size<1>::type f1(param<copy_constructible<>, _self&>); +size<2>::type f1(...); + +void test_ref() { + BOOST_STATIC_ASSERT(sizeof(f1(a1)) == 1); + BOOST_STATIC_ASSERT(sizeof(f1(a2)) == 2); + BOOST_STATIC_ASSERT(sizeof(f1(a3)) == 1); + BOOST_STATIC_ASSERT(sizeof(f1(a4)) == 1); + BOOST_STATIC_ASSERT(sizeof(f1(a5)) == 2); + BOOST_STATIC_ASSERT(sizeof(f1(a6)) == 2); + + BOOST_STATIC_ASSERT(sizeof(f1(a7())) == 2); + BOOST_STATIC_ASSERT(sizeof(f1(a8())) == 2); + BOOST_STATIC_ASSERT(sizeof(f1(a9())) == 1); + BOOST_STATIC_ASSERT(sizeof(f1(a10())) == 1); + BOOST_STATIC_ASSERT(sizeof(f1(a11())) == 2); + BOOST_STATIC_ASSERT(sizeof(f1(a12())) == 2); + + BOOST_STATIC_ASSERT(sizeof(f1(i)) == 2); + BOOST_STATIC_ASSERT(sizeof(f1(1)) == 2); + + // Make sure that the constructors are actually instantiated + param<copy_constructible<>, _self&> c1 = a1; + // param<copy_constructible<>, _self&> c2 = a2; + param<copy_constructible<>, _self&> c3 = a3; + param<copy_constructible<>, _self&> c4 = a4; + // param<copy_constructible<>, _self&> c5 = a5; + // param<copy_constructible<>, _self&> c6 = a6; + + // param<copy_constructible<>, _self&> c7 = a7(); + // param<copy_constructible<>, _self&> c8 = a8(); + param<copy_constructible<>, _self&> c9 = a9(); + param<copy_constructible<>, _self&> c10 = a10(); + // param<copy_constructible<>, _self&> c11 = a11(); + // param<copy_constructible<>, _self&> c12 = a12(); +} + +size<1>::type f2(param<copy_constructible<>, const _self&>); +size<2>::type f2(...); + +void test_cref() { + BOOST_STATIC_ASSERT(sizeof(f2(a1)) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a2)) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a3)) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a4)) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a5)) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a6)) == 1); + + BOOST_STATIC_ASSERT(sizeof(f2(a7())) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a8())) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a9())) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a10())) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a11())) == 1); + BOOST_STATIC_ASSERT(sizeof(f2(a12())) == 1); + + BOOST_STATIC_ASSERT(sizeof(f2(i)) == 2); + BOOST_STATIC_ASSERT(sizeof(f2(1)) == 2); + + // Make sure that the constructors are actually instantiated + param<copy_constructible<>, const _self&> c1 = a1; + param<copy_constructible<>, const _self&> c2 = a2; + param<copy_constructible<>, const _self&> c3 = a3; + param<copy_constructible<>, const _self&> c4 = a4; + param<copy_constructible<>, const _self&> c5 = a5; + param<copy_constructible<>, const _self&> c6 = a6; + + param<copy_constructible<>, const _self&> c7 = a7(); + param<copy_constructible<>, const _self&> c8 = a8(); + param<copy_constructible<>, const _self&> c9 = a9(); + param<copy_constructible<>, const _self&> c10 = a10(); + param<copy_constructible<>, const _self&> c11 = a11(); + param<copy_constructible<>, const _self&> c12 = a12(); +} + +size<1>::type f3(param<copy_constructible<>, _self>); +size<2>::type f3(...); + +void test_val() { + BOOST_STATIC_ASSERT(sizeof(f3(a1)) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a2)) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a3)) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a4)) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a5)) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a6)) == 1); + + BOOST_STATIC_ASSERT(sizeof(f3(a7())) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a8())) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a9())) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a10())) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a11())) == 1); + BOOST_STATIC_ASSERT(sizeof(f3(a12())) == 1); + + BOOST_STATIC_ASSERT(sizeof(f3(i)) == 2); + BOOST_STATIC_ASSERT(sizeof(f3(1)) == 2); + + // Make sure that the constructors are actually instantiated + param<copy_constructible<>, _self> c1 = a1; + param<copy_constructible<>, _self> c2 = a2; + param<copy_constructible<>, _self> c3 = a3; + param<copy_constructible<>, _self> c4 = a4; + param<copy_constructible<>, _self> c5 = a5; + param<copy_constructible<>, _self> c6 = a6; + + param<copy_constructible<>, _self> c7 = a7(); + param<copy_constructible<>, _self> c8 = a8(); + param<copy_constructible<>, _self> c9 = a9(); + param<copy_constructible<>, _self> c10 = a10(); + param<copy_constructible<>, _self> c11 = a11(); + param<copy_constructible<>, _self> c12 = a12(); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +size<1>::type f4(param<copy_constructible<>, _self&&>); +size<2>::type f4(...); + +void test_rref() { + BOOST_STATIC_ASSERT(sizeof(f4(a1)) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a2)) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a3)) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a4)) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a5)) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a6)) == 2); + + BOOST_STATIC_ASSERT(sizeof(f4(a7())) == 1); + BOOST_STATIC_ASSERT(sizeof(f4(a8())) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a9())) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a10())) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a11())) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(a12())) == 2); + + BOOST_STATIC_ASSERT(sizeof(f4(i)) == 2); + BOOST_STATIC_ASSERT(sizeof(f4(1)) == 2); + + // Make sure that the constructors are actually instantiated + // param<copy_constructible<>, _self&&> c1 = a1; + // param<copy_constructible<>, _self&&> c2 = a2; + // param<copy_constructible<>, _self&&> c3 = a3; + // param<copy_constructible<>, _self&&> c4 = a4; + // param<copy_constructible<>, _self&&> c5 = a5; + // param<copy_constructible<>, _self&&> c6 = a6; + + param<copy_constructible<>, _self&&> c7 = a7(); + // param<copy_constructible<>, _self&&> c8 = a8(); + // param<copy_constructible<>, _self&&> c9 = a9(); + // param<copy_constructible<>, _self&&> c10 = a10(); + // param<copy_constructible<>, _self&&> c11 = a11(); + // param<copy_constructible<>, _self&&> c12 = a12(); +} + +#endif + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + +// Test conversion sequence rank + +size<1>::type f5(param<copy_constructible<>, _self&>); +size<2>::type f5(param<copy_constructible<>, const _self&>); + +void test_ref_cref() { + BOOST_STATIC_ASSERT(sizeof(f5(a1)) == 1); + BOOST_STATIC_ASSERT(sizeof(f5(a2)) == 2); + BOOST_STATIC_ASSERT(sizeof(f5(a3)) == 1); + BOOST_STATIC_ASSERT(sizeof(f5(a4)) == 1); + BOOST_STATIC_ASSERT(sizeof(f5(a5)) == 2); + BOOST_STATIC_ASSERT(sizeof(f5(a6)) == 2); + + BOOST_STATIC_ASSERT(sizeof(f5(a7())) == 2); + BOOST_STATIC_ASSERT(sizeof(f5(a8())) == 2); + BOOST_STATIC_ASSERT(sizeof(f5(a9())) == 1); + BOOST_STATIC_ASSERT(sizeof(f5(a10())) == 1); + BOOST_STATIC_ASSERT(sizeof(f5(a11())) == 2); + BOOST_STATIC_ASSERT(sizeof(f5(a12())) == 2); +} + +size<1>::type f6(param<copy_constructible<>, _self&>); +size<2>::type f6(param<copy_constructible<>, _self&&>); + +void test_ref_rref() { + BOOST_STATIC_ASSERT(sizeof(f6(a1)) == 1); + // BOOST_STATIC_ASSERT(sizeof(f6(a2)) == 2); + BOOST_STATIC_ASSERT(sizeof(f6(a3)) == 1); + BOOST_STATIC_ASSERT(sizeof(f6(a4)) == 1); + // BOOST_STATIC_ASSERT(sizeof(f6(a5)) == 2); + // BOOST_STATIC_ASSERT(sizeof(f6(a6)) == 2); + + BOOST_STATIC_ASSERT(sizeof(f6(a7())) == 2); + // BOOST_STATIC_ASSERT(sizeof(f6(a8())) == 2); + BOOST_STATIC_ASSERT(sizeof(f6(a9())) == 1); + BOOST_STATIC_ASSERT(sizeof(f6(a10())) == 1); + // BOOST_STATIC_ASSERT(sizeof(f6(a11())) == 2); + // BOOST_STATIC_ASSERT(sizeof(f6(a12())) == 2); +} + +size<1>::type f7(param<copy_constructible<>, const _self&>); +size<2>::type f7(param<copy_constructible<>, _self&&>); + +void test_cref_rref() { + BOOST_STATIC_ASSERT(sizeof(f7(a1)) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a2)) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a3)) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a4)) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a5)) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a6)) == 1); + + BOOST_STATIC_ASSERT(sizeof(f7(a7())) == 2); + BOOST_STATIC_ASSERT(sizeof(f7(a8())) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a9())) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a10())) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a11())) == 1); + BOOST_STATIC_ASSERT(sizeof(f7(a12())) == 1); +} + +#endif diff --git a/src/boost/libs/type_erasure/test/test_reference.cpp b/src/boost/libs/type_erasure/test/test_reference.cpp new file mode 100644 index 000000000..abf4b0cc3 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_reference.cpp @@ -0,0 +1,82 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +class no_destroy +{ +protected: + ~no_destroy() {} +}; + +class with_destroy : public no_destroy +{ +public: + ~with_destroy() {} +}; + +template<class T = _self> +struct common : ::boost::mpl::vector< + destructible<T>, + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_basic) +{ + typedef ::boost::mpl::vector<typeid_<> > test_concept; + with_destroy val; + any<test_concept, _self&> x(static_cast<no_destroy&>(val)); + no_destroy& ref = any_cast<no_destroy&>(x); + BOOST_CHECK_EQUAL(&ref, &val); +} + +BOOST_AUTO_TEST_CASE(test_increment) +{ + typedef ::boost::mpl::vector<incrementable<> > test_concept; + int i = 0; + any<test_concept, _self&> x(i); + ++x; + BOOST_CHECK_EQUAL(i, 1); +} + +BOOST_AUTO_TEST_CASE(test_add) +{ + typedef ::boost::mpl::vector<common<>, addable<> > test_concept; + int i = 1; + int j = 2; + any<test_concept, _self&> x(i); + any<test_concept, _self&> y(j); + any<test_concept, _self> z(x + y); + int k = any_cast<int>(z); + BOOST_CHECK_EQUAL(k, 3); +} + +BOOST_AUTO_TEST_CASE(test_mixed_add) +{ + typedef ::boost::mpl::vector<common<>, addable<> > test_concept; + int i = 1; + int j = 2; + any<test_concept, _self&> x(i); + any<test_concept, _self> y(j); + any<test_concept, _self> z(x + y); + int k = any_cast<int>(z); + BOOST_CHECK_EQUAL(k, 3); +} diff --git a/src/boost/libs/type_erasure/test/test_relaxed.cpp b/src/boost/libs/type_erasure/test/test_relaxed.cpp new file mode 100644 index 000000000..e92ec3793 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_relaxed.cpp @@ -0,0 +1,36 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/relaxed.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_simple) +{ + typedef ::boost::mpl::vector<copy_constructible<>, addable<>, relaxed> src_concept; + any<src_concept> x(1); + any<src_concept> y(2.0); + BOOST_CHECK_THROW(x + y, bad_function_call); +} diff --git a/src/boost/libs/type_erasure/test/test_same_type.cpp b/src/boost/libs/type_erasure/test/test_same_type.cpp new file mode 100644 index 000000000..f02f2ac0c --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_same_type.cpp @@ -0,0 +1,87 @@ +// Boost.TypeErasure library +// +// Copyright 2012 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/deduced.hpp> +#include <boost/type_erasure/same_type.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/remove_pointer.hpp> +#include <boost/type_traits/is_same.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_AUTO_TEST_CASE(test_deduce_dereference) +{ + typedef ::boost::mpl::vector< + copy_constructible<>, + typeid_<_a>, + dereferenceable<deduced<boost::remove_pointer<_self> >&>, + same_type<deduced<boost::remove_pointer<_self> >, _a> + > test_concept; + int i; + + any<test_concept> x(&i); + any<test_concept, _a&> y(*x); + BOOST_CHECK_EQUAL(&any_cast<int&>(y), &i); +} + +BOOST_MPL_ASSERT(( + boost::is_same< + deduced<boost::remove_pointer<_self> >::type, + deduced<boost::remove_pointer<_self> > >)); + +BOOST_MPL_ASSERT(( + boost::is_same<deduced<boost::remove_pointer<int*> >::type, int >)); + +BOOST_AUTO_TEST_CASE(test_duplicate) +{ + typedef ::boost::mpl::vector< + copy_constructible<>, + typeid_<_a>, + dereferenceable<deduced<boost::remove_pointer<_self> >&>, + same_type<deduced<boost::remove_pointer<_self> >, _a>, + same_type<deduced<boost::remove_pointer<_self> >, _a> + > test_concept; + int i; + + any<test_concept> x(&i); + any<test_concept, _a&> y(*x); + BOOST_CHECK_EQUAL(&any_cast<int&>(y), &i); +} + +BOOST_AUTO_TEST_CASE(test_convert) +{ + typedef ::boost::mpl::vector< + copy_constructible<>, + typeid_<_a>, + dereferenceable<deduced<boost::remove_pointer<_self> >&>, + same_type<deduced<boost::remove_pointer<_self> >, _a> + > test_concept_src; + typedef ::boost::mpl::vector< + copy_constructible<_b>, + typeid_<_c>, + dereferenceable<deduced<boost::remove_pointer<_b> >&, _b>, + same_type<deduced<boost::remove_pointer<_b> >, _c> + > test_concept_dest; + int i; + + any<test_concept_src> x1(&i); + any<test_concept_src, _a&> y1(*x1); + any<test_concept_dest, _b> x2(x1); + any<test_concept_dest, _c&> y2(*x2); + BOOST_CHECK_EQUAL(&any_cast<int&>(y2), &i); +} diff --git a/src/boost/libs/type_erasure/test/test_sfinae.cpp b/src/boost/libs/type_erasure/test/test_sfinae.cpp new file mode 100644 index 000000000..28f250ea9 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_sfinae.cpp @@ -0,0 +1,58 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_traits/is_constructible.hpp> +#include <boost/type_traits/is_copy_constructible.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/assert.hpp> + +using namespace boost::type_erasure; + +#if defined(BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS) + +using boost::is_copy_constructible; + +template<class T> +using is_move_constructible = boost::is_constructible<T, T&&>; + +template<class T> +using is_mutable_constructible = boost::is_constructible<T, T&>; + +using move_constructible = boost::mpl::vector<constructible<_self(_self&&)>, destructible<> >; +using mutable_copy = boost::mpl::vector<constructible<_self(_self&)>, destructible<> >; + +BOOST_MPL_ASSERT_NOT((is_copy_constructible<any<destructible<> > >)); +BOOST_MPL_ASSERT((is_copy_constructible<any<copy_constructible<> > >)); +BOOST_MPL_ASSERT_NOT((is_copy_constructible<any<move_constructible> >)); + +// only is_copy_constructible seems to work on msvc and +// even that breaks when we add a non-const copy constructor. +#if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1912)) && \ + !BOOST_WORKAROUND(BOOST_GCC, < 70000) && \ + !BOOST_WORKAROUND(__clang__major__, < 4) + +BOOST_MPL_ASSERT_NOT((is_mutable_constructible<any<destructible<> > >)); +BOOST_MPL_ASSERT_NOT((is_move_constructible<any<destructible<> > >)); + +BOOST_MPL_ASSERT((is_mutable_constructible<any<copy_constructible<> > >)); +BOOST_MPL_ASSERT((is_move_constructible<any<copy_constructible<> > >)); + +BOOST_MPL_ASSERT_NOT((is_mutable_constructible<any<move_constructible> >)); +BOOST_MPL_ASSERT((is_move_constructible<any<move_constructible> >)); + +BOOST_MPL_ASSERT((is_mutable_constructible<any<mutable_copy> >)); +BOOST_MPL_ASSERT_NOT((is_copy_constructible<any<mutable_copy> >)); +BOOST_MPL_ASSERT_NOT((is_move_constructible<any<mutable_copy> >)); + +#endif + +#endif diff --git a/src/boost/libs/type_erasure/test/test_stream.cpp b/src/boost/libs/type_erasure/test/test_stream.cpp new file mode 100644 index 000000000..30b3482da --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_stream.cpp @@ -0,0 +1,245 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/mpl/vector.hpp> +#include <sstream> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +BOOST_AUTO_TEST_CASE(test_output_int) +{ + typedef ostreamable<_a, int> test_concept; + std::ostringstream ss; + any<test_concept, _a&> x(ss); + x << 17; + BOOST_CHECK_EQUAL(ss.str(), "17"); +} + +BOOST_AUTO_TEST_CASE(test_output_int_wide) +{ + typedef ostreamable<_a, int> test_concept; + std::wostringstream ss; + any<test_concept, _a&> x(ss); + x << 17; + BOOST_CHECK(ss.str() == L"17"); +} + +BOOST_AUTO_TEST_CASE(test_output_int_any) +{ + typedef boost::mpl::vector<ostreamable<>, copy_constructible<> > test_concept; + std::ostringstream ss; + any<test_concept> x(10); + ss << x; + BOOST_CHECK_EQUAL(ss.str(), "10"); +} + +BOOST_AUTO_TEST_CASE(test_output_int_any_wide) +{ + typedef boost::mpl::vector<ostreamable<std::wostream>, copy_constructible<> > test_concept; + std::wostringstream ss; + any<test_concept> x(10); + ss << x; + BOOST_CHECK(ss.str() == L"10"); +} + +BOOST_AUTO_TEST_CASE(test_output_both_any) +{ + typedef boost::mpl::vector<ostreamable<_a>, copy_constructible<> > test_concept; + std::ostringstream ss; + int val = 19; + tuple<test_concept, _a&, _self> t(ss, val); + get<0>(t) << get<1>(t); + BOOST_CHECK_EQUAL(ss.str(), "19"); +} + +BOOST_AUTO_TEST_CASE(test_output_both_any_wide) +{ + typedef boost::mpl::vector<ostreamable<_a>, copy_constructible<> > test_concept; + std::wostringstream ss; + int val = 19; + tuple<test_concept, _a&, _self> t(ss, val); + get<0>(t) << get<1>(t); + BOOST_CHECK(ss.str() == L"19"); +} + +BOOST_AUTO_TEST_CASE(test_output_overload_all) +{ + typedef boost::mpl::vector< + ostreamable<_a>, + ostreamable<_a, int>, + ostreamable<_b>, + ostreamable<_b, int>, + ostreamable<>, + ostreamable<std::wostream>, + copy_constructible<> + > test_concept; + { + std::ostringstream ss; + std::wostringstream wss; + int val = 2; + tuple<test_concept, _a&, _b&, _self> t(ss, wss, val); + get<0>(t) << get<2>(t); + get<1>(t) << get<2>(t); + BOOST_CHECK_EQUAL(ss.str(), "2"); + BOOST_CHECK(wss.str() == L"2"); + } + { + std::ostringstream ss; + std::wostringstream wss; + int val = 2; + tuple<test_concept, _a&, _b&, _self> t(ss, wss, val); + get<0>(t) << 3; + get<1>(t) << 3; + BOOST_CHECK_EQUAL(ss.str(), "3"); + BOOST_CHECK(wss.str() == L"3"); + } + { + std::ostringstream ss; + std::wostringstream wss; + int val = 5; + tuple<test_concept, _a&, _b&, _self> t(ss, wss, val); + ss << get<2>(t); + wss << get<2>(t); + BOOST_CHECK_EQUAL(ss.str(), "5"); + BOOST_CHECK(wss.str() == L"5"); + } + { + std::ostringstream ss; + std::wostringstream wss; + int val = 5; + tuple<test_concept, _a&, _b&, _self> t(ss, wss, val); + // we can't do anything with these, but it should + // still compile. + any<test_concept, const _a&> os(get<0>(t)); + any<test_concept, const _b&> wos(get<1>(t)); + } +} + + +BOOST_AUTO_TEST_CASE(test_input_int) +{ + typedef istreamable<_a, int> test_concept; + std::istringstream ss("17"); + int i; + any<test_concept, _a&> x(ss); + x >> i; + BOOST_CHECK_EQUAL(i, 17); +} + +BOOST_AUTO_TEST_CASE(test_input_int_wide) +{ + typedef istreamable<_a, int> test_concept; + std::wistringstream ss(L"17"); + int i; + any<test_concept, _a&> x(ss); + x >> i; + BOOST_CHECK_EQUAL(i, 17); +} + +BOOST_AUTO_TEST_CASE(test_input_int_any) +{ + typedef istreamable<> test_concept; + std::istringstream ss("10"); + int i; + any<test_concept, _self&> x(i); + ss >> x; + BOOST_CHECK_EQUAL(i, 10); +} + +BOOST_AUTO_TEST_CASE(test_input_int_any_wide) +{ + typedef istreamable<std::wistream> test_concept; + std::wistringstream ss(L"10"); + int i; + any<test_concept, _self&> x(i); + ss >> x; + BOOST_CHECK_EQUAL(i, 10); +} + +BOOST_AUTO_TEST_CASE(test_input_both_any) +{ + typedef istreamable<_a> test_concept; + std::istringstream ss("19"); + int i; + tuple<test_concept, _a&, _self&> t(ss, i); + get<0>(t) >> get<1>(t); + BOOST_CHECK_EQUAL(i, 19); +} + +BOOST_AUTO_TEST_CASE(test_input_both_any_wide) +{ + typedef istreamable<_a> test_concept; + std::wistringstream ss(L"19"); + int i; + tuple<test_concept, _a&, _self&> t(ss, i); + get<0>(t) >> get<1>(t); + BOOST_CHECK_EQUAL(i, 19); +} + +BOOST_AUTO_TEST_CASE(test_input_overload_all) +{ + typedef boost::mpl::vector< + istreamable<_a>, + istreamable<_a, int>, + istreamable<_b>, + istreamable<_b, int>, + istreamable<>, + istreamable<std::wistream> + > test_concept; + { + std::istringstream ss("2"); + std::wistringstream wss(L"3"); + int i = 0; + tuple<test_concept, _a&, _b&, _self&> t(ss, wss, i); + get<0>(t) >> get<2>(t); + BOOST_CHECK_EQUAL(i, 2); + get<1>(t) >> get<2>(t); + BOOST_CHECK_EQUAL(i, 3); + } + { + std::istringstream ss("5"); + std::wistringstream wss(L"7"); + int i = 0; + tuple<test_concept, _a&, _b&, _self&> t(ss, wss, i); + get<0>(t) >> i; + BOOST_CHECK_EQUAL(i, 5); + get<1>(t) >> i; + BOOST_CHECK_EQUAL(i, 7); + } + { + std::istringstream ss("11"); + std::wistringstream wss(L"13"); + int i = 0; + tuple<test_concept, _a&, _b&, _self&> t(ss, wss, i); + ss >> get<2>(t); + BOOST_CHECK_EQUAL(i, 11); + wss >> get<2>(t); + BOOST_CHECK_EQUAL(i, 13); + } + { + std::istringstream ss; + std::wistringstream wss; + int val = 5; + tuple<test_concept, _a&, _b&, _self&> t(ss, wss, val); + // we can't do anything with these, but it should + // still compile. + any<test_concept, const _a&> is(get<0>(t)); + any<test_concept, const _b&> wis(get<1>(t)); + } +} diff --git a/src/boost/libs/type_erasure/test/test_subscript.cpp b/src/boost/libs/type_erasure/test/test_subscript.cpp new file mode 100644 index 000000000..8cacc059a --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_subscript.cpp @@ -0,0 +1,68 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_basic) +{ + typedef ::boost::mpl::vector<common<>, subscriptable<int&> > test_concept; + int i[5]; + any<test_concept> x(&i[0]); + BOOST_CHECK_EQUAL(&x[0], &i[0]); +} + +BOOST_AUTO_TEST_CASE(test_basic_const) +{ + typedef ::boost::mpl::vector<common<>, subscriptable<int&, const _self> > test_concept; + int i[5]; + const any<test_concept> x(&i[0]); + BOOST_CHECK_EQUAL(&x[0], &i[0]); +} + +BOOST_AUTO_TEST_CASE(test_any_result) +{ + typedef ::boost::mpl::vector<common<>, common<_a>, subscriptable<_a&, const _self> > test_concept; + typedef ::boost::mpl::map< + ::boost::mpl::pair<_self, int*>, + ::boost::mpl::pair<_a, int> + > types; + int i[5]; + any<test_concept> x(&i[0], make_binding<types>()); + any<test_concept, _a&> y(x[0]); + BOOST_CHECK_EQUAL(any_cast<int*>(&y), &i[0]); +} + +BOOST_AUTO_TEST_CASE(test_any_result_const) +{ + typedef ::boost::mpl::vector<common<>, common<_a>, subscriptable<const _a&, const _self> > test_concept; + typedef ::boost::mpl::map< + ::boost::mpl::pair<_self, const int*>, + ::boost::mpl::pair<_a, int> + > types; + const int i[5] = { 0, 0, 0, 0, 0 }; + any<test_concept> x(&i[0], make_binding<types>()); + any<test_concept, const _a&> y(x[0]); + BOOST_CHECK_EQUAL(any_cast<const int*>(&y), &i[0]); +} diff --git a/src/boost/libs/type_erasure/test/test_tuple.cpp b/src/boost/libs/type_erasure/test/test_tuple.cpp new file mode 100644 index 000000000..aa8efd58a --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_tuple.cpp @@ -0,0 +1,92 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/fusion/include/at_c.hpp> +#include <boost/fusion/include/front.hpp> +#include <boost/fusion/include/back.hpp> +#include <boost/fusion/include/size.hpp> +#include <boost/fusion/include/empty.hpp> +#include <boost/fusion/include/begin.hpp> +#include <boost/fusion/include/end.hpp> +#include <boost/fusion/include/distance.hpp> +#include <boost/fusion/include/next.hpp> +#include <boost/fusion/include/prior.hpp> +#include <boost/fusion/include/equal_to.hpp> +#include <boost/fusion/include/advance.hpp> +#include <boost/fusion/include/deref.hpp> +#include <boost/fusion/include/value_of.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_same) +{ + tuple<common<_a>, _a, _a> t(1, 2); + BOOST_CHECK_EQUAL(any_cast<int&>(get<0>(t)), 1); + BOOST_CHECK_EQUAL(any_cast<int&>(get<1>(t)), 2); +} + +BOOST_AUTO_TEST_CASE(test_degenerate) +{ + tuple<boost::mpl::vector<> > t; +} + +template<class T> +typename T::value_type get_static(T) { return T::value; } + +BOOST_AUTO_TEST_CASE(test_fusion) +{ + typedef boost::mpl::vector<common<_a>, common<_b>, addable<_a, _b> > test_concept; + tuple<test_concept, _a, _b> t(2.0, 1); + BOOST_CHECK_EQUAL(any_cast<double&>(boost::fusion::at_c<0>(t)), 2.0); + BOOST_CHECK_EQUAL(any_cast<int&>(boost::fusion::at_c<1>(t)), 1); + BOOST_CHECK_EQUAL(any_cast<double&>(boost::fusion::front(t)), 2.0); + BOOST_CHECK_EQUAL(any_cast<int&>(boost::fusion::back(t)), 1); + BOOST_CHECK_EQUAL(get_static(boost::fusion::empty(t)), false); + BOOST_CHECK_EQUAL(get_static(boost::fusion::size(t)), 2); + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::begin(t), boost::fusion::end(t))), 2); + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::next(boost::fusion::begin(t)), boost::fusion::end(t))), 1); + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::begin(t), boost::fusion::prior(boost::fusion::end(t)))), 1); + + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::advance_c<2>(boost::fusion::begin(t)), boost::fusion::end(t))), 0); + BOOST_CHECK_EQUAL(any_cast<double&>(boost::fusion::deref(boost::fusion::begin(t))), 2.0); +} + +BOOST_AUTO_TEST_CASE(test_fusion_const) +{ + typedef boost::mpl::vector<common<_a>, common<_b>, addable<_a, _b> > test_concept; + const tuple<test_concept, _a, _b> t(2.0, 1); + BOOST_CHECK_EQUAL(any_cast<const double&>(boost::fusion::at_c<0>(t)), 2.0); + BOOST_CHECK_EQUAL(any_cast<const int&>(boost::fusion::at_c<1>(t)), 1); + BOOST_CHECK_EQUAL(any_cast<const double&>(boost::fusion::front(t)), 2.0); + BOOST_CHECK_EQUAL(any_cast<const int&>(boost::fusion::back(t)), 1); + BOOST_CHECK_EQUAL(get_static(boost::fusion::empty(t)), false); + BOOST_CHECK_EQUAL(get_static(boost::fusion::size(t)), 2); + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::begin(t), boost::fusion::end(t))), 2); + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::next(boost::fusion::begin(t)), boost::fusion::end(t))), 1); + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::begin(t), boost::fusion::prior(boost::fusion::end(t)))), 1); + + BOOST_CHECK_EQUAL(get_static(boost::fusion::distance(boost::fusion::advance_c<2>(boost::fusion::begin(t)), boost::fusion::end(t))), 0); + BOOST_CHECK_EQUAL(any_cast<const double&>(boost::fusion::deref(boost::fusion::begin(t))), 2.0); +} diff --git a/src/boost/libs/type_erasure/test/test_typeid_of.cpp b/src/boost/libs/type_erasure/test/test_typeid_of.cpp new file mode 100644 index 000000000..6fe77ae99 --- /dev/null +++ b/src/boost/libs/type_erasure/test/test_typeid_of.cpp @@ -0,0 +1,71 @@ +// Boost.TypeErasure library +// +// Copyright 2011 Steven Watanabe +// +// 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) +// +// $Id$ + +#include <boost/type_erasure/any.hpp> +#include <boost/type_erasure/tuple.hpp> +#include <boost/type_erasure/builtin.hpp> +#include <boost/type_erasure/operators.hpp> +#include <boost/type_erasure/any_cast.hpp> +#include <boost/type_erasure/typeid_of.hpp> +#include <boost/mpl/vector.hpp> + +#define BOOST_TEST_MAIN +#include <boost/test/unit_test.hpp> + +using namespace boost::type_erasure; + +template<class T = _self> +struct common : ::boost::mpl::vector< + copy_constructible<T>, + typeid_<T> +> {}; + +BOOST_AUTO_TEST_CASE(test_val) +{ + typedef common<> test_concept; + any<test_concept> x(2); + BOOST_CHECK(typeid_of(x) == typeid(int)); + const any<test_concept> y(2); + BOOST_CHECK(typeid_of(y) == typeid(int)); +} + +BOOST_AUTO_TEST_CASE(test_ref) +{ + typedef common<> test_concept; + int i; + any<test_concept, _self&> x(i); + BOOST_CHECK(typeid_of(x) == typeid(int)); + const any<test_concept, _self&> y(i); + BOOST_CHECK(typeid_of(y) == typeid(int)); +} + +BOOST_AUTO_TEST_CASE(test_cref) +{ + typedef common<> test_concept; + int i; + any<test_concept, const _self&> x(i); + BOOST_CHECK(typeid_of(x) == typeid(int)); + const any<test_concept, const _self&> y(i); + BOOST_CHECK(typeid_of(y) == typeid(int)); +} + +BOOST_AUTO_TEST_CASE(test_binding) +{ + typedef boost::mpl::vector<common<_a>, common<_b> > test_concept; + binding<test_concept> b = + make_binding< + boost::mpl::map< + boost::mpl::pair<_a, int>, + boost::mpl::pair<_b, double> + > + >(); + BOOST_CHECK(typeid_of<_a>(b) == typeid(int)); + BOOST_CHECK(typeid_of<_b>(b) == typeid(double)); +} |