[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
# 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 ;

View File

@@ -0,0 +1,75 @@
# 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 path ;
using boostbook ;
using quickbook ;
using doxygen ;
path-constant here : . ;
path-constant boost-root : ../../.. ;
# Figure out where the root of the boost tree is relative
# to the html directory.
local BOOST_ROOT = [ path.relative-to
[ path.join [ path.pwd ] html ]
[ path.root
[ path.make $(boost-root) ]
[ path.pwd ] ] ] ;
xml type_erasure : type_erasure.qbk : <dependency>reference ;
doxygen reference
:
[ glob ../../../boost/type_erasure/*.hpp ]
:
<doxygen:param>EXPAND_ONLY_PREDEF=YES
<doxygen:param>"ALIASES= \\
CopyConstructible=\"<a href=\\\"$(BOOST_ROOT)/doc/html/CopyConstructible.html\\\">CopyConstructible</a>\" \\
Concept=\"@xmlonly<link linkend=\\\"boost_typeerasure.conceptdef\\\">Concept</link>@endxmlonly\" \\
call=\"@xmlonly<functionname alt=\\\"boost::type_erasure::call\\\">call</functionname>@endxmlonly\" \\
any_cast=\"@xmlonly<functionname alt=\\\"boost::type_erasure::any_cast\\\">any_cast</functionname>@endxmlonly\" \\
typeid_of=\"@xmlonly<functionname alt=\\\"boost::type_erasure::typeid_of\\\">typeid_of</functionname>@endxmlonly\" \\
binding_of=\"@xmlonly<functionname alt=\\\"boost::type_erasure::binding_of\\\">binding_of</functionname>@endxmlonly\" \\
is_empty=\"@xmlonly<functionname alt=\\\"boost::type_erasure::is_empty\\\">is_empty</functionname>@endxmlonly\" \\
require_match=\"@xmlonly<functionname alt=\\\"boost::type_erasure::require_match\\\">require_match</functionname>@endxmlonly\" "
<doxygen:param>"PREDEFINED= \\
\"BOOST_TYPE_ERASURE_DOXYGEN=1\" \\
\"BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(name, op)=template<class T = _self> struct name { static void apply(T&); };\" \\
\"BOOST_TYPE_ERASURE_UNARY_OPERATOR(name, op)=template<class T = _self, class R = T> struct name { static R apply(const T&); };\" \\
\"BOOST_TYPE_ERASURE_BINARY_OPERATOR(name, op)=template<class T = _self, class U = T, class R = T> struct name { static R apply(const T&, const U&); };\" \\
\"BOOST_TYPE_ERASURE_ASSIGNMENT_OPERATOR(name, op)=template<class T = _self, class U = T> struct name { static void apply(T&, const U&); };\" \\
\"table_arg=table\" \\
\"binding_arg=binding\" \\
\"data_arg=data\""
<doxygen:param>HIDE_UNDOC_MEMBERS=NO
<doxygen:param>QUIET=YES
<doxygen:param>WARN_IF_UNDOCUMENTED=NO
<doxygen:param>EXTRACT_PRIVATE=NO
<doxygen:param>ENABLE_PREPROCESSING=YES
<doxygen:param>MACRO_EXPANSION=YES
<doxygen:param>SEARCH_INCLUDES=NO
;
boostbook standalone
:
type_erasure
:
<dependency>reference
<xsl:param>boost.root=../../../..
;
###############################################################################
alias boostdoc
: type_erasure
:
: <dependency>reference
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,552 @@
[library Boost.TypeErasure
[quickbook 1.5]
[authors [Watanabe, Steven]]
[copyright 2011-2013 Steven Watanabe]
[license
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])
]
[purpose Runtime polymorphism based on concepts]
]
[def __any [classref boost::type_erasure::any any]]
[def __any_cast [funcref boost::type_erasure::any_cast any_cast]]
[def __tuple [classref boost::type_erasure::tuple tuple]]
[def __rebind_any [classref boost::type_erasure::rebind_any rebind_any]]
[def __derived [classref boost::type_erasure::derived derived]]
[def __concept_interface [classref boost::type_erasure::concept_interface concept_interface]]
[def __constructible [classref boost::type_erasure::constructible constructible]]
[def __destructible [classref boost::type_erasure::destructible destructible]]
[def __copy_constructible [classref boost::type_erasure::copy_constructible copy_constructible]]
[def __assignable [classref boost::type_erasure::assignable assignable]]
[def __typeid_ [classref boost::type_erasure::typeid_ typeid_]]
[def __relaxed [classref boost::type_erasure::relaxed relaxed]]
[def __binding [classref boost::type_erasure::binding binding]]
[def __static_binding [classref boost::type_erasure::static_binding static_binding]]
[def __placeholder [classref boost::type_erasure::placeholder placeholder]]
[def __call [funcref boost::type_erasure::call call]]
[def __deduced [classref boost::type_erasure::deduced deduced]]
[def __as_param [classref boost::type_erasure::as_param as_param]]
[def __addable [classref boost::type_erasure::addable addable]]
[def __subtractable [classref boost::type_erasure::subtractable subtractable]]
[def __multipliable [classref boost::type_erasure::multipliable multipliable]]
[def __dividable [classref boost::type_erasure::dividable dividable]]
[def __modable [classref boost::type_erasure::modable modable]]
[def __bitandable [classref boost::type_erasure::bitandable bitandable]]
[def __bitorable [classref boost::type_erasure::bitorable bitorable]]
[def __bitxorable [classref boost::type_erasure::bitxorable bitxorable]]
[def __left_shiftable [classref boost::type_erasure::left_shiftable left_shiftable]]
[def __right_shiftable [classref boost::type_erasure::right_shiftable right_shiftable]]
[def __add_assignable [classref boost::type_erasure::add_assignable add_assignable]]
[def __subtract_assignable [classref boost::type_erasure::subtract_assignable subtract_assignable]]
[def __multiply_assignable [classref boost::type_erasure::multiply_assignable multiply_assignable]]
[def __divide_assignable [classref boost::type_erasure::divide_assignable divide_assignable]]
[def __mod_assignable [classref boost::type_erasure::mod_assignable mod_assignable]]
[def __bitand_assignable [classref boost::type_erasure::bitand_assignable bitand_assignable]]
[def __bitor_assignable [classref boost::type_erasure::bitor_assignable bitor_assignable]]
[def __bitxor_assignable [classref boost::type_erasure::bitxor_assignable bitxor_assignable]]
[def __left_shift_assignable [classref boost::type_erasure::left_shift_assignable left_shift_assignable]]
[def __right_shift_assignable [classref boost::type_erasure::right_shift_assignable right_shift_assignable]]
[def __incrementable [classref boost::type_erasure::incrementable incrementable]]
[def __decrementable [classref boost::type_erasure::decrementable decrementable]]
[def __negatable [classref boost::type_erasure::negatable negatable]]
[def __complementable [classref boost::type_erasure::complementable complementable]]
[def __dereferenceable [classref boost::type_erasure::dereferenceable dereferenceable]]
[def __callable [classref boost::type_erasure::callable callable]]
[def __subscriptable [classref boost::type_erasure::subscriptable subscriptable]]
[def __equality_comparable [classref boost::type_erasure::equality_comparable equality_comparable]]
[def __less_than_comparable [classref boost::type_erasure::less_than_comparable less_than_comparable]]
[def __ostreamable [classref boost::type_erasure::ostreamable ostreamable]]
[def __istreamable [classref boost::type_erasure::istreamable istreamable]]
[def __iterator [classref boost::type_erasure::iterator iterator]]
[def __forward_iterator [classref boost::type_erasure::forward_iterator forward_iterator]]
[def __bidirectional_iterator [classref boost::type_erasure::bidirectional_iterator bidirectional_iterator]]
[def __random_access_iterator [classref boost::type_erasure::random_access_iterator random_access_iterator]]
[def __same_type [classref boost::type_erasure::same_type same_type]]
[def __BOOST_TYPE_ERASURE_MEMBER [macroref BOOST_TYPE_ERASURE_MEMBER]]
[def __BOOST_TYPE_ERASURE_FREE [macroref BOOST_TYPE_ERASURE_FREE]]
[section:introduction Introduction]
The Boost.TypeErasure library provides runtime polymorphism
in C++ that is more flexible than that provided by the
core language.
C++ has two distinct kinds of polymorphism,
virtual functions and templates, each of which has
its own advantages and disadvantages.
* Virtual functions are not resolved until runtime,
while templates are always resolved at compile
time. If your types can vary at runtime (for
example, if they depend on user input), then
static polymorphism with templates doesn't help much.
* Virtual functions can be used with separate compilation.
The body of a template has to be available
in every translation unit in which it is used,
slowing down compiles and increasing rebuilds.
* Virtual functions automatically make the requirements
on the arguments explicit. Templates are only
checked when they're instantiated, requiring
extra work in testing, assertions, and documentation.
* The compiler creates a new copy of each function
template every time it is instantiated. This
allows better optimization, because the compiler
knows everything statically, but it also causes
a significant increase of binary sizes.
* Templates support Value semantics. Objects that
"behave like an int" and are not shared are easier
to reason about. To use virtual functions, on
the other hand, you have to use (smart) pointers
or references.
* Template libraries can allow third-party types to
be adapted non-intrusively for seamless interoperability.
With virtual functions, you have to create a wrapper
that inherits from the base class.
* Templates can handle constraints involving
multiple types. For example, std::for_each
takes an iterator range and a function that
can be called on the elements of the range.
Virtual functions aren't really able to
express such constraints.
The Boost.TypeErasure library combines the superior
abstraction capabilities of templates, with the
runtime flexibility of virtual functions.
Boost includes several special cases of this kind
of polymorphism:
* `boost::any` for CopyConstructible types.
* `boost::function` for objects that can be called like functions.
* Boost.Range provides `any_iterator`.
Boost.TypeErasure generalizes this to support arbitrary
requirements and provides a
[link boost_typeerasure.predef predefined set of common concepts]
[endsect]
[section:reading How to read this documentation]
To avoid excessive verbosity, all the examples
assume that a few using directives are in place.
namespace mpl = boost::mpl;
using namespace boost::type_erasure;
[endsect]
[section:basic Basic Usage]
[import ../example/basic.cpp]
[basic]
[endsect]
[section Composing Concepts]
[import ../example/compose.cpp]
[compose]
[endsect]
[section:multi Functions with Multiple Arguments]
[import ../example/multi.cpp]
[multi]
[endsect]
[section:concept Concepts in Depth]
[section:custom Defining Custom Concepts]
[import ../example/custom.cpp]
[custom]
[endsect]
[section:overload Overloading]
[import ../example/overload.cpp]
[overload]
[endsect]
[section:concept_map Concept Maps]
[import ../example/concept_map.cpp]
[concept_map]
[endsect]
[section:overload Associated Types]
[import ../example/associated.cpp]
[associated]
[endsect]
[endsect]
[section:any Using Any]
[section:construction Construction]
[import ../example/construction.cpp]
[construction]
[endsect]
[section Conversions]
[import ../example/convert.cpp]
[convert]
[endsect]
[section:references References]
[import ../example/references.cpp]
[references]
[endsect]
[section:limit Syntax Limitations]
In most cases using an any has the same
syntax as using the underlying object.
However, there are a few cases where
this is not possible to implement.
An __any reference is proxy and cannot
be used in contexts where a real
reference is required. In particular,
__forward_iterator does not create
a conforming ForwardIterator (unless
the value_type is fixed.) Another
difference is that all operations
which do not take at least one __any
argument have to be passed the type
information explicitly. Static member
functions and constructors can fall in
this category. All this means that generic
algorithms might not work when applied to
__any arguments.
[endsect]
[endsect]
[section:examples Examples]
[section:print_sequence A polymorphic range formatter]
[import ../example/print_sequence.cpp]
[print_sequence]
[endsect]
[section:printf A type-safe printf]
[import ../example/printf.cpp]
[printf]
[endsect]
[section:multifunction Boost.Function with multiple signatures]
[import ../example/multifunction.cpp]
[multifunction]
[endsect]
[endsect]
[section:conceptdef Concept Definitions]
A Concept defines a set of constraints on the types that
are stored in an __any.
There are three kinds of concepts.
# The library defines a number of [link boost_typeerasure.predef predefined concepts].
Most of these are equivalent to user-defined concepts, but a few
require special handling.
# Users can define their own primitive concepts as described below.
The macros __BOOST_TYPE_ERASURE_MEMBER and __BOOST_TYPE_ERASURE_FREE
define concepts of this form.
# Any MPL Forward Sequence whose elements are
concepts is also a concept. This allows concepts
to be composed easily.
Each primitive concept defines a single function.
A primitive concept must be a specialization of a
class template, with a static member function
called `apply`, which will be executed when the
function is dispatched by __call. The template
can only take template type parameters. non-type
template parameters and template template parameters
are not allowed.
The template parameters of the concept
may involve placeholders. The following are
considered.
* Each template argument may be a cv and/or reference
qualified placeholder type.
* If a template argument is a function type, its
arguments and return type may be cv/reference
qualified placeholders.
Any other placeholders are ignored.
A concept is instantiated by constructing an
__any from a raw value or by constructing a __binding.
When a concept is instantiated with a specific
set of type bindings, each placeholder is bound
to a cv-unqualified non-reference type. After
replacing each placeholder in the template argument
list with the type that it binds to, the following
must hold.
* The number of arguments of apply in the
bound concept must be the same as the number
of arguments in the unbound concept.
* The arguments and return type of apply in the
bound concept can be derived from the corresponding
arguments and the return type in the unbound concept
as follows: If the argument in the unbound concept is a
placeholder with optional cv and reference
qualifiers, then the argument in the bound
concept can be found by replacing the placeholder.
Otherwise, the argument in the unbound concept
must be the same as the argument in the bound concept.
// Correct.
template<class T = _self>
struct foo1 {
static void apply(const T& t) { t.foo(); }
};
// Wrong. The signature of apply is different from the
// primary template
template<>
struct foo1<int> {
static void apply(int i);
};
// Wrong. A concept must be a template
struct foo2 {
static void apply(const _self&);
};
// Wrong. apply must be static
template<class T = _self>
struct foo3 {
void apply(const T&);
};
// Wrong. apply cannot be overloaded
template<class T = _self>
struct foo3 {
static void apply(T&);
static void apply(const T&);
};
// Wrong. Only top level placeholders are detected
template<class T>
struct foo4;
template<class T>
struct foo4<boost::mpl::vector<T> > {
static void apply(const T&);
};
// Wrong. Template template parameters are not allowed.
template<template<class> class T>
struct foo5
{
static void apply(T<int>&);
};
[endsect]
[section:predef Predefined Concepts]
In the following tables, `T` and `U` are the types that the operation
applies to, `R` is the result type. `T` always defaults
to `_self` to match the default behavior of any. These
concepts assume normal semantics. Thus, comparison
operators always return bool, and references will be
added to the arguments and results as appropriate.
Except as otherwise noted, primitive concepts defined by
the library can be specialized to provide concept maps.
__copy_constructible, and the iterator concepts cannot
be specialized because they are composites. __constructible,
__destructible, __typeid_, and __same_type cannot be
specialized because they require special handling in
the library.
[table:special Special Members
[[concept][notes]]
[[__constructible`<Sig>`][-]]
[[__copy_constructible`<T>`][-]]
[[__destructible`<T>`][-]]
[[__assignable`<T, U = T>`][-]]
[[__typeid_`<T>`][-]]
]
[table:unary Unary Operators
[[operator][concept][notes]]
[[`operator++`][__incrementable`<T>`][There is no separate post-increment]]
[[`operator--`][__decrementable`<T>`][There is no separate post-decrement]]
[[`operator*`][__dereferenceable`<R, T>`][`R` should usually be a reference]]
[[`operator~`][__complementable`<T, R = T>`][-]]
[[`operator-`][__negatable`<T, R = T>`][-]]
]
[table:binary Binary Operators
[[operator][concept][notes]]
[[`operator+`][__addable`<T, U = T, R = T>`][-]]
[[`operator-`][__subtractable`<T, U = T, R = T>`][-]]
[[`operator*`][__multipliable`<T, U = T, R = T>`][-]]
[[`operator/`][__dividable`<T, U = T, R = T>`][-]]
[[`operator%`][__modable`<T, U = T, R = T>`][-]]
[[`operator&`][__bitandable`<T, U = T, R = T>`][-]]
[[`operator|`][__bitorable`<T, U = T, R = T>`][-]]
[[`operator^`][__bitxorable`<T, U = T, R = T>`][-]]
[[`operator<<`][__left_shiftable`<T, U = T, R = T>`][-]]
[[`operator>>`][__right_shiftable`<T, U = T, R = T>`][-]]
[[`operator==` and `!=`][__equality_comparable`<T, U = T>`][`!=` is implemented in terms of `==`]]
[[`operator<`, `>`, `<=`, and `>=`][__less_than_comparable`<T, U = T>`][All are implemented in terms of `<`]]
[[`operator+=`][__add_assignable`<T, U = T>`][-]]
[[`operator-=`][__subtract_assignable`<T, U = T>`][-]]
[[`operator*=`][__multiply_assignable`<T, U = T>`][-]]
[[`operator/=`][__divide_assignable`<T, U = T>`][-]]
[[`operator%=`][__mod_assignable`<T, U = T>`][-]]
[[`operator&=`][__bitand_assignable`<T, U = T>`][-]]
[[`operator|=`][__bitor_assignable`<T, U = T>`][-]]
[[`operator^=`][__bitxor_assignable`<T, U = T>`][-]]
[[`operator<<=`][__left_shift_assignable`<T, U = T>`][-]]
[[`operator>>=`][__right_shift_assignable`<T, U = T>`][-]]
[[`operator<<`][__ostreamable`<Os = std::ostream, T = _self>`][-]]
[[`operator>>`][__istreamable`<Is = std::istream, T = _self>`][-]]
]
[table:misc Miscellaneous Operators
[[operator][concept][notes]]
[[`operator()`][__callable`<Sig, T>`][`Sig` should be a function type. T may be const qualified.]]
[[`operator[]`][__subscriptable`<R, T, N = std::ptrdiff_t>`][`R` should usually be a reference. `T` can be optionally const qualified.]]
]
[table:iterator Iterator Concepts
[[concept][notes]]
[[__iterator`<Traversal, T, Reference, Difference>`][Use __same_type to control the iterator's value type.]]
[[__forward_iterator`<T, Reference, Difference>`][-]]
[[__bidirectional_iterator`<T, Reference, Difference>`][-]]
[[__random_access_iterator`<T, Reference, Difference>`][-]]
]
[table:special Special Concepts
[[concept][notes]]
[[__same_type`<T>`][Indicates that two types are the same.]]
]
[endsect]
[xinclude reference.xml]
[section:rationale Rationale]
[section Why do I have to specify the presence of a destructor explicitly?]
When using references the destructor isn't needed.
By not assuming it implicitly, we allow capturing
types with private or protected destructors by reference.
For the sake of consistency, it must be specified
when capturing by value as well.
[endsect]
[section Why non-member functions?]
The members of __any can be customized. By using
free functions, we guarantee that we don't interfere
with anything that a user might want.
[endsect]
[section:placeholder Why are the placeholders called `_a`, `_b` and not `_1` `_2`]
An earlier version of the library used the names `_1`, `_2`, etc.
instead of `_a`, `_b`, etc. This caused a certain amount
of confusion because the numbered placeholders are
already used with a somewhat different meaning by several
other libraries including Boost/Std Bind, Boost.Phoenix,
and Boost.MPL. I eventually decided that since the
placeholders represented named parameters instead of positional parameters,
letters were more appropriate than numbers.
[endsect]
[section:ref Why not use `boost::ref` for references?]
Boost.Function allows you to use `boost::ref` to store
a reference to a function object. However, in the
general case treating references and values in the
same way causes inconsistent behavior that is difficult
to reason about. If Boost.TypeErasure handled references
like this, then, when you copy an __any, you would have
no idea whether the new object is a real copy or
just a new reference to the same underlying object.
Boost.Function can get away with it, because it doesn't
expose any mutating operations on the stored function object.
Another method that has been proposed is only to
keep a reference the first time.
int i = 2;
any x = ref(i);
any y = x; // makes a copy
Unfortunately, this doesn't handle all use cases,
as there is no reliable way to return such a reference
from a function. In addition it adds overhead whether
it's needed or not, as we would have to add a flag
to any to keep track of whether or not it is storing
a reference. (The alternate method of storing this
in the "`clone`" method in the vtable is impossibly complex
to implement given the decoupled vtables that
Boost.TypeErasure uses and it still adds overhead.).
[endsect]
[endsect]
[section:future Future Work]
These are just some ideas. There is absolutely no
guarantee that any of them will ever be implemented.
* Use SBO.
* Allow more control over vtable layout.
* Attempt to reuse sub-tables in conversions.
* Allow "dynamic_cast". This requires creating
a global registry of concept mappings.
* Optimize the compile-time cost.
[endsect]
[section:acknowledgements Acknowledgements]
The name `any` and an early ancestor of my placeholder
system were taken from Alexander Nasonov's DynamicAny library.
Thanks to review manager, Lorenzo Caminiti
and all who participated in the formal review:
* Christophe Henry
* Paul Bristow
* Karsten Ahnert
* Pete Bartlett
* Sebastian Redl
* Hossein Haeri
* Trigve Siver
* Julien Nitard
* Eric Niebler
* Fabio Fracassi
* Joel de Guzman
* Alec Chapman
* Larry Evans
* Vincente J. Botet Escriba
* Marcus Werle
* Andrey Semashev
* Dave Abrahams
* Thomas Jordan
[endsect]
[section:related Related Work]
There are a number of similar libraries in existence. I'm aware
of at least three.
* [@http://www.coderage.com/interfaces/ Boost.Interfaces] by Jonathan Turkanis
* [@http://stlab.adobe.com/group__poly__related.html Adobe Poly]
* [@http://cpp-experiment.sourceforge.net/boost/libs/dynamic_any/doc/ Boost.dynamic_any] by Alexander Nasonov
[endsect]

View File

@@ -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 ;

View File

@@ -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]
//]

View File

@@ -0,0 +1,160 @@
// 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((has_push_back), push_back, 1)
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`.
The second parameter is the name of the member
function and the last macro parameter indicates
the number of arguments which is `1` since `push_back`
is unary. 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.
*/
/*`
There's actually another __placeholder here. The second
parameter of `has_push_back` defaults to `_self`. If
we wanted to define a const member function, we would
have to change it to `const _self`, as shown below.
*/
BOOST_TYPE_ERASURE_MEMBER((has_empty), empty, 0)
bool is_empty(any<has_empty<bool(), const _self>, const _self&> x) {
return x.empty();
}
/*`
For free functions, we can use the macro __BOOST_TYPE_ERASURE_FREE.
*/
BOOST_TYPE_ERASURE_FREE((has_getline), getline, 2)
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]
//]

View File

@@ -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]
//]

View File

@@ -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]
//]

View File

@@ -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]
//]

View File

@@ -0,0 +1,58 @@
// 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>
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]
//]

View File

@@ -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]
//]

View File

@@ -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]
//]

View File

@@ -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 });
}
//]

View File

@@ -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]
//]

View File

@@ -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);
}
//]

View File

@@ -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);
}
//]

View File

@@ -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]
//]

View File

@@ -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>

View File

@@ -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>"
]
}

View File

@@ -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();
}
}

View File

@@ -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)
import testing ;
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 ;
compile test_param.cpp ;
compile test_is_subconcept.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_binding_convert_no_mapping.cpp ;
compile-fail fail_increment_discard_const.cpp ;
compile-fail fail_ref_assign.cpp ;
compile-fail fail_cref_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 ;

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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<> >());
}

View File

@@ -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> > >());
}

View File

@@ -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> > >());
}

View File

@@ -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> > >());
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -0,0 +1,197 @@
// 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_basic)
{
typedef ::boost::mpl::vector<common<>, assignable<> > test_concept;
any<test_concept> x(1);
int* ip = any_cast<int*>(&x);
any<test_concept> y(2);
x = y;
BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
// make sure that we're actually using assignment
// of the underlying object, not copy and swap.
BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
}
BOOST_AUTO_TEST_CASE(test_basic_relaxed)
{
typedef ::boost::mpl::vector<common<>, assignable<>, relaxed > test_concept;
any<test_concept> x(1);
int* ip = any_cast<int*>(&x);
any<test_concept> y(2);
x = y;
BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
// make sure that we're actually using assignment
// of the underlying object, not copy and swap.
BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
}
BOOST_AUTO_TEST_CASE(test_relaxed_no_copy)
{
typedef ::boost::mpl::vector<
destructible<>,
typeid_<>,
assignable<>,
relaxed
> test_concept;
any<test_concept> x(1);
int* ip = any_cast<int*>(&x);
any<test_concept> y(2);
x = y;
BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
// make sure that we're actually using assignment
// of the underlying object, not copy and swap.
BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
}
BOOST_AUTO_TEST_CASE(test_relaxed_no_assign)
{
typedef ::boost::mpl::vector<
common<>,
relaxed
> test_concept;
any<test_concept> x(1);
any<test_concept> y(2);
x = y;
BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
}
BOOST_AUTO_TEST_CASE(test_dynamic_fallback)
{
typedef ::boost::mpl::vector<common<>, assignable<>, relaxed> test_concept;
any<test_concept> x(1);
any<test_concept> y(2.0);
x = y;
BOOST_CHECK_EQUAL(any_cast<double>(x), 2.0);
}
BOOST_AUTO_TEST_CASE(test_dynamic_fail)
{
typedef ::boost::mpl::vector<destructible<>, typeid_<>, assignable<>, relaxed> test_concept;
any<test_concept> x(1);
any<test_concept> y(2.0);
BOOST_CHECK_THROW(x = y, bad_function_call);
}
BOOST_AUTO_TEST_CASE(test_basic_int)
{
typedef ::boost::mpl::vector<common<>, assignable<_self, int> > test_concept;
any<test_concept> x(1);
int* ip = any_cast<int*>(&x);
x = 2;
BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
// make sure that we're actually using assignment
// of the underlying object, not copy and swap.
BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
}
BOOST_AUTO_TEST_CASE(test_basic_relaxed_int)
{
typedef ::boost::mpl::vector<common<>, assignable<_self, int>, relaxed > test_concept;
any<test_concept> x(1);
int* ip = any_cast<int*>(&x);
x = 2;
BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
// make sure that we're actually using assignment
// of the underlying object, not copy and swap.
BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
}
BOOST_AUTO_TEST_CASE(test_relaxed_no_copy_int)
{
typedef ::boost::mpl::vector<
destructible<>,
typeid_<>,
assignable<_self, int>,
relaxed
> test_concept;
any<test_concept> x(1);
int* ip = any_cast<int*>(&x);
x = 2;
BOOST_CHECK_EQUAL(any_cast<int>(x), 2);
// make sure that we're actually using assignment
// of the underlying object, not copy and swap.
BOOST_CHECK_EQUAL(any_cast<int*>(&x), ip);
}
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);
}
BOOST_AUTO_TEST_CASE(test_basic_ref)
{
typedef ::boost::mpl::vector<common<>, assignable<> > test_concept;
int i = 1;
any<test_concept, _self&> x(i);
any<test_concept> y(2);
x = y;
BOOST_CHECK_EQUAL(i, 2);
}
BOOST_AUTO_TEST_CASE(test_basic_relaxed_ref)
{
typedef ::boost::mpl::vector<common<>, assignable<>, relaxed > test_concept;
int i = 1;
any<test_concept, _self&> x(i);
any<test_concept> y(2);
x = y;
BOOST_CHECK_EQUAL(i, 2);
}
BOOST_AUTO_TEST_CASE(test_relaxed_no_assign_ref)
{
typedef ::boost::mpl::vector<
common<>,
relaxed
> test_concept;
int i = 1;
any<test_concept, _self&> x(i);
any<test_concept> y(2);
x = y;
BOOST_CHECK_EQUAL(i, 1);
BOOST_CHECK_EQUAL(any_cast<int*>(&x), any_cast<int*>(&y));
}
BOOST_AUTO_TEST_CASE(test_dynamic_fallback_ref)
{
typedef ::boost::mpl::vector<common<>, assignable<>, relaxed> test_concept;
int i = 1;
any<test_concept, _self&> x(i);
any<test_concept> y(2.0);
x = y;
BOOST_CHECK_EQUAL(any_cast<double>(x), 2.0);
}

View File

@@ -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));
}

View File

@@ -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);
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 >));

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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> >));
}

View File

@@ -0,0 +1,112 @@
// 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

View File

@@ -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);
}

View File

@@ -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));
}

View File

@@ -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> > >));

View File

@@ -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));
}

View File

@@ -0,0 +1,138 @@
// 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_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_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);
}
#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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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));
}

View File

@@ -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_FUNCTION_REFERENCE_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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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]);
}

View File

@@ -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);
}

View File

@@ -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));
}