// | |
// (C) Copyright Jeremy Siek 2000. | |
// Copyright 2002 The Trustees of Indiana University. | |
// | |
// 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) | |
// | |
// Revision History: | |
// 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) | |
// 02 April 2001: Removed limits header altogether. (Jeremy Siek) | |
// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock) | |
// | |
// See http://www.boost.org/libs/concept_check for documentation. | |
#ifndef BOOST_CONCEPT_CHECKS_HPP | |
# define BOOST_CONCEPT_CHECKS_HPP | |
# include <boost/concept/assert.hpp> | |
# include <boost/iterator.hpp> | |
# include <boost/type_traits/conversion_traits.hpp> | |
# include <utility> | |
# include <boost/type_traits/is_same.hpp> | |
# include <boost/type_traits/is_void.hpp> | |
# include <boost/mpl/assert.hpp> | |
# include <boost/mpl/bool.hpp> | |
# include <boost/detail/workaround.hpp> | |
# include <boost/detail/iterator.hpp> | |
# include <boost/concept/usage.hpp> | |
# include <boost/concept/detail/concept_def.hpp> | |
namespace boost | |
{ | |
// | |
// Backward compatibility | |
// | |
template <class Model> | |
inline void function_requires(Model* = 0) | |
{ | |
BOOST_CONCEPT_ASSERT((Model)); | |
} | |
template <class T> inline void ignore_unused_variable_warning(T const&) {} | |
# define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ | |
BOOST_CONCEPT_ASSERT((ns::concept<type_var>)) | |
# define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ | |
BOOST_CONCEPT_ASSERT((ns::concept<type_var1,type_var2>)) | |
# define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ | |
BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3>)) | |
# define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ | |
BOOST_CONCEPT_ASSERT((ns::concept<tv1,tv2,tv3,tv4>)) | |
// | |
// Begin concept definitions | |
// | |
BOOST_concept(Integer, (T)) | |
{ | |
BOOST_CONCEPT_USAGE(Integer) | |
{ | |
x.error_type_must_be_an_integer_type(); | |
} | |
private: | |
T x; | |
}; | |
template <> struct Integer<char> {}; | |
template <> struct Integer<signed char> {}; | |
template <> struct Integer<unsigned char> {}; | |
template <> struct Integer<short> {}; | |
template <> struct Integer<unsigned short> {}; | |
template <> struct Integer<int> {}; | |
template <> struct Integer<unsigned int> {}; | |
template <> struct Integer<long> {}; | |
template <> struct Integer<unsigned long> {}; | |
# if defined(BOOST_HAS_LONG_LONG) | |
template <> struct Integer< ::boost::long_long_type> {}; | |
template <> struct Integer< ::boost::ulong_long_type> {}; | |
# elif defined(BOOST_HAS_MS_INT64) | |
template <> struct Integer<__int64> {}; | |
template <> struct Integer<unsigned __int64> {}; | |
# endif | |
BOOST_concept(SignedInteger,(T)) { | |
BOOST_CONCEPT_USAGE(SignedInteger) { | |
x.error_type_must_be_a_signed_integer_type(); | |
} | |
private: | |
T x; | |
}; | |
template <> struct SignedInteger<signed char> { }; | |
template <> struct SignedInteger<short> {}; | |
template <> struct SignedInteger<int> {}; | |
template <> struct SignedInteger<long> {}; | |
# if defined(BOOST_HAS_LONG_LONG) | |
template <> struct SignedInteger< ::boost::long_long_type> {}; | |
# elif defined(BOOST_HAS_MS_INT64) | |
template <> struct SignedInteger<__int64> {}; | |
# endif | |
BOOST_concept(UnsignedInteger,(T)) { | |
BOOST_CONCEPT_USAGE(UnsignedInteger) { | |
x.error_type_must_be_an_unsigned_integer_type(); | |
} | |
private: | |
T x; | |
}; | |
template <> struct UnsignedInteger<unsigned char> {}; | |
template <> struct UnsignedInteger<unsigned short> {}; | |
template <> struct UnsignedInteger<unsigned int> {}; | |
template <> struct UnsignedInteger<unsigned long> {}; | |
# if defined(BOOST_HAS_LONG_LONG) | |
template <> struct UnsignedInteger< ::boost::ulong_long_type> {}; | |
# elif defined(BOOST_HAS_MS_INT64) | |
template <> struct UnsignedInteger<unsigned __int64> {}; | |
# endif | |
//=========================================================================== | |
// Basic Concepts | |
BOOST_concept(DefaultConstructible,(TT)) | |
{ | |
BOOST_CONCEPT_USAGE(DefaultConstructible) { | |
TT a; // require default constructor | |
ignore_unused_variable_warning(a); | |
} | |
}; | |
BOOST_concept(Assignable,(TT)) | |
{ | |
BOOST_CONCEPT_USAGE(Assignable) { | |
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL | |
a = b; // require assignment operator | |
#endif | |
const_constraints(b); | |
} | |
private: | |
void const_constraints(const TT& x) { | |
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL | |
a = x; // const required for argument to assignment | |
#else | |
ignore_unused_variable_warning(x); | |
#endif | |
} | |
private: | |
TT a; | |
TT b; | |
}; | |
BOOST_concept(CopyConstructible,(TT)) | |
{ | |
BOOST_CONCEPT_USAGE(CopyConstructible) { | |
TT a(b); // require copy constructor | |
TT* ptr = &a; // require address of operator | |
const_constraints(a); | |
ignore_unused_variable_warning(ptr); | |
} | |
private: | |
void const_constraints(const TT& a) { | |
TT c(a); // require const copy constructor | |
const TT* ptr = &a; // require const address of operator | |
ignore_unused_variable_warning(c); | |
ignore_unused_variable_warning(ptr); | |
} | |
TT b; | |
}; | |
#if (defined _MSC_VER) | |
# pragma warning( push ) | |
# pragma warning( disable : 4510 ) // default constructor could not be generated | |
# pragma warning( disable : 4610 ) // object 'class' can never be instantiated - user-defined constructor required | |
#endif | |
// The SGI STL version of Assignable requires copy constructor and operator= | |
BOOST_concept(SGIAssignable,(TT)) | |
{ | |
BOOST_CONCEPT_USAGE(SGIAssignable) { | |
TT c(a); | |
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL | |
a = b; // require assignment operator | |
#endif | |
const_constraints(b); | |
ignore_unused_variable_warning(c); | |
} | |
private: | |
void const_constraints(const TT& x) { | |
TT c(x); | |
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL | |
a = x; // const required for argument to assignment | |
#endif | |
ignore_unused_variable_warning(c); | |
} | |
TT a; | |
TT b; | |
}; | |
#if (defined _MSC_VER) | |
# pragma warning( pop ) | |
#endif | |
BOOST_concept(Convertible,(X)(Y)) | |
{ | |
BOOST_CONCEPT_USAGE(Convertible) { | |
Y y = x; | |
ignore_unused_variable_warning(y); | |
} | |
private: | |
X x; | |
}; | |
// The C++ standard requirements for many concepts talk about return | |
// types that must be "convertible to bool". The problem with this | |
// requirement is that it leaves the door open for evil proxies that | |
// define things like operator|| with strange return types. Two | |
// possible solutions are: | |
// 1) require the return type to be exactly bool | |
// 2) stay with convertible to bool, and also | |
// specify stuff about all the logical operators. | |
// For now we just test for convertible to bool. | |
template <class TT> | |
void require_boolean_expr(const TT& t) { | |
bool x = t; | |
ignore_unused_variable_warning(x); | |
} | |
BOOST_concept(EqualityComparable,(TT)) | |
{ | |
BOOST_CONCEPT_USAGE(EqualityComparable) { | |
require_boolean_expr(a == b); | |
require_boolean_expr(a != b); | |
} | |
private: | |
TT a, b; | |
}; | |
BOOST_concept(LessThanComparable,(TT)) | |
{ | |
BOOST_CONCEPT_USAGE(LessThanComparable) { | |
require_boolean_expr(a < b); | |
} | |
private: | |
TT a, b; | |
}; | |
// This is equivalent to SGI STL's LessThanComparable. | |
BOOST_concept(Comparable,(TT)) | |
{ | |
BOOST_CONCEPT_USAGE(Comparable) { | |
require_boolean_expr(a < b); | |
require_boolean_expr(a > b); | |
require_boolean_expr(a <= b); | |
require_boolean_expr(a >= b); | |
} | |
private: | |
TT a, b; | |
}; | |
#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ | |
BOOST_concept(NAME, (First)(Second)) \ | |
{ \ | |
BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ | |
private: \ | |
bool constraints_() { return a OP b; } \ | |
First a; \ | |
Second b; \ | |
} | |
#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ | |
BOOST_concept(NAME, (Ret)(First)(Second)) \ | |
{ \ | |
BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ | |
private: \ | |
Ret constraints_() { return a OP b; } \ | |
First a; \ | |
Second b; \ | |
} | |
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp); | |
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp); | |
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOp); | |
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOp); | |
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOp); | |
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOp); | |
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOp); | |
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOp); | |
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOp); | |
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOp); | |
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOp); | |
//=========================================================================== | |
// Function Object Concepts | |
BOOST_concept(Generator,(Func)(Return)) | |
{ | |
BOOST_CONCEPT_USAGE(Generator) { test(is_void<Return>()); } | |
private: | |
void test(boost::mpl::false_) | |
{ | |
// Do we really want a reference here? | |
const Return& r = f(); | |
ignore_unused_variable_warning(r); | |
} | |
void test(boost::mpl::true_) | |
{ | |
f(); | |
} | |
Func f; | |
}; | |
BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) | |
{ | |
BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void<Return>()); } | |
private: | |
void test(boost::mpl::false_) | |
{ | |
f(arg); // "priming the pump" this way keeps msvc6 happy (ICE) | |
Return r = f(arg); | |
ignore_unused_variable_warning(r); | |
} | |
void test(boost::mpl::true_) | |
{ | |
f(arg); | |
} | |
#if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ | |
&& BOOST_WORKAROUND(__GNUC__, > 3))) | |
// Declare a dummy construktor to make gcc happy. | |
// It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. | |
// (warning: non-static reference "const double& boost::UnaryFunction<YourClassHere>::arg" | |
// in class without a constructor [-Wuninitialized]) | |
UnaryFunction(); | |
#endif | |
Func f; | |
Arg arg; | |
}; | |
BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) | |
{ | |
BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void<Return>()); } | |
private: | |
void test(boost::mpl::false_) | |
{ | |
f(first,second); | |
Return r = f(first, second); // require operator() | |
(void)r; | |
} | |
void test(boost::mpl::true_) | |
{ | |
f(first,second); | |
} | |
#if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ | |
&& BOOST_WORKAROUND(__GNUC__, > 3))) | |
// Declare a dummy constructor to make gcc happy. | |
// It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. | |
// (warning: non-static reference "const double& boost::BinaryFunction<YourClassHere>::arg" | |
// in class without a constructor [-Wuninitialized]) | |
BinaryFunction(); | |
#endif | |
Func f; | |
First first; | |
Second second; | |
}; | |
BOOST_concept(UnaryPredicate,(Func)(Arg)) | |
{ | |
BOOST_CONCEPT_USAGE(UnaryPredicate) { | |
require_boolean_expr(f(arg)); // require operator() returning bool | |
} | |
private: | |
#if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ | |
&& BOOST_WORKAROUND(__GNUC__, > 3))) | |
// Declare a dummy constructor to make gcc happy. | |
// It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. | |
// (warning: non-static reference "const double& boost::UnaryPredicate<YourClassHere>::arg" | |
// in class without a constructor [-Wuninitialized]) | |
UnaryPredicate(); | |
#endif | |
Func f; | |
Arg arg; | |
}; | |
BOOST_concept(BinaryPredicate,(Func)(First)(Second)) | |
{ | |
BOOST_CONCEPT_USAGE(BinaryPredicate) { | |
require_boolean_expr(f(a, b)); // require operator() returning bool | |
} | |
private: | |
#if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ | |
&& BOOST_WORKAROUND(__GNUC__, > 3))) | |
// Declare a dummy constructor to make gcc happy. | |
// It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. | |
// (warning: non-static reference "const double& boost::BinaryPredicate<YourClassHere>::arg" | |
// in class without a constructor [-Wuninitialized]) | |
BinaryPredicate(); | |
#endif | |
Func f; | |
First a; | |
Second b; | |
}; | |
// use this when functor is used inside a container class like std::set | |
BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) | |
: BinaryPredicate<Func, First, Second> | |
{ | |
BOOST_CONCEPT_USAGE(Const_BinaryPredicate) { | |
const_constraints(f); | |
} | |
private: | |
void const_constraints(const Func& fun) { | |
// operator() must be a const member function | |
require_boolean_expr(fun(a, b)); | |
} | |
#if (BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4) \ | |
&& BOOST_WORKAROUND(__GNUC__, > 3))) | |
// Declare a dummy constructor to make gcc happy. | |
// It seems the compiler can not generate a sensible constructor when this is instantiated with a refence type. | |
// (warning: non-static reference "const double& boost::Const_BinaryPredicate<YourClassHere>::arg" | |
// in class without a constructor [-Wuninitialized]) | |
Const_BinaryPredicate(); | |
#endif | |
Func f; | |
First a; | |
Second b; | |
}; | |
BOOST_concept(AdaptableGenerator,(Func)(Return)) | |
: Generator<Func, typename Func::result_type> | |
{ | |
typedef typename Func::result_type result_type; | |
BOOST_CONCEPT_USAGE(AdaptableGenerator) | |
{ | |
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); | |
} | |
}; | |
BOOST_concept(AdaptableUnaryFunction,(Func)(Return)(Arg)) | |
: UnaryFunction<Func, typename Func::result_type, typename Func::argument_type> | |
{ | |
typedef typename Func::argument_type argument_type; | |
typedef typename Func::result_type result_type; | |
~AdaptableUnaryFunction() | |
{ | |
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); | |
BOOST_CONCEPT_ASSERT((Convertible<Arg, argument_type>)); | |
} | |
}; | |
BOOST_concept(AdaptableBinaryFunction,(Func)(Return)(First)(Second)) | |
: BinaryFunction< | |
Func | |
, typename Func::result_type | |
, typename Func::first_argument_type | |
, typename Func::second_argument_type | |
> | |
{ | |
typedef typename Func::first_argument_type first_argument_type; | |
typedef typename Func::second_argument_type second_argument_type; | |
typedef typename Func::result_type result_type; | |
~AdaptableBinaryFunction() | |
{ | |
BOOST_CONCEPT_ASSERT((Convertible<result_type, Return>)); | |
BOOST_CONCEPT_ASSERT((Convertible<First, first_argument_type>)); | |
BOOST_CONCEPT_ASSERT((Convertible<Second, second_argument_type>)); | |
} | |
}; | |
BOOST_concept(AdaptablePredicate,(Func)(Arg)) | |
: UnaryPredicate<Func, Arg> | |
, AdaptableUnaryFunction<Func, bool, Arg> | |
{ | |
}; | |
BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second)) | |
: BinaryPredicate<Func, First, Second> | |
, AdaptableBinaryFunction<Func, bool, First, Second> | |
{ | |
}; | |
//=========================================================================== | |
// Iterator Concepts | |
BOOST_concept(InputIterator,(TT)) | |
: Assignable<TT> | |
, EqualityComparable<TT> | |
{ | |
typedef typename boost::detail::iterator_traits<TT>::value_type value_type; | |
typedef typename boost::detail::iterator_traits<TT>::difference_type difference_type; | |
typedef typename boost::detail::iterator_traits<TT>::reference reference; | |
typedef typename boost::detail::iterator_traits<TT>::pointer pointer; | |
typedef typename boost::detail::iterator_traits<TT>::iterator_category iterator_category; | |
BOOST_CONCEPT_USAGE(InputIterator) | |
{ | |
BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>)); | |
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>)); | |
TT j(i); | |
(void)*i; // require dereference operator | |
++j; // require preincrement operator | |
i++; // require postincrement operator | |
} | |
private: | |
TT i; | |
}; | |
BOOST_concept(OutputIterator,(TT)(ValueT)) | |
: Assignable<TT> | |
{ | |
BOOST_CONCEPT_USAGE(OutputIterator) { | |
++i; // require preincrement operator | |
i++; // require postincrement operator | |
*i++ = t; // require postincrement and assignment | |
} | |
private: | |
TT i, j; | |
ValueT t; | |
}; | |
BOOST_concept(ForwardIterator,(TT)) | |
: InputIterator<TT> | |
{ | |
BOOST_CONCEPT_USAGE(ForwardIterator) | |
{ | |
BOOST_CONCEPT_ASSERT((Convertible< | |
BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category | |
, std::forward_iterator_tag | |
>)); | |
typename InputIterator<TT>::reference r = *i; | |
ignore_unused_variable_warning(r); | |
} | |
private: | |
TT i; | |
}; | |
BOOST_concept(Mutable_ForwardIterator,(TT)) | |
: ForwardIterator<TT> | |
{ | |
BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) { | |
*i++ = *i; // require postincrement and assignment | |
} | |
private: | |
TT i; | |
}; | |
BOOST_concept(BidirectionalIterator,(TT)) | |
: ForwardIterator<TT> | |
{ | |
BOOST_CONCEPT_USAGE(BidirectionalIterator) | |
{ | |
BOOST_CONCEPT_ASSERT((Convertible< | |
BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category | |
, std::bidirectional_iterator_tag | |
>)); | |
--i; // require predecrement operator | |
i--; // require postdecrement operator | |
} | |
private: | |
TT i; | |
}; | |
BOOST_concept(Mutable_BidirectionalIterator,(TT)) | |
: BidirectionalIterator<TT> | |
, Mutable_ForwardIterator<TT> | |
{ | |
BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator) | |
{ | |
*i-- = *i; // require postdecrement and assignment | |
} | |
private: | |
TT i; | |
}; | |
BOOST_concept(RandomAccessIterator,(TT)) | |
: BidirectionalIterator<TT> | |
, Comparable<TT> | |
{ | |
BOOST_CONCEPT_USAGE(RandomAccessIterator) | |
{ | |
BOOST_CONCEPT_ASSERT((Convertible< | |
BOOST_DEDUCED_TYPENAME BidirectionalIterator<TT>::iterator_category | |
, std::random_access_iterator_tag | |
>)); | |
i += n; // require assignment addition operator | |
i = i + n; i = n + i; // require addition with difference type | |
i -= n; // require assignment subtraction operator | |
i = i - n; // require subtraction with difference type | |
n = i - j; // require difference operator | |
(void)i[n]; // require element access operator | |
} | |
private: | |
TT a, b; | |
TT i, j; | |
typename boost::detail::iterator_traits<TT>::difference_type n; | |
}; | |
BOOST_concept(Mutable_RandomAccessIterator,(TT)) | |
: RandomAccessIterator<TT> | |
, Mutable_BidirectionalIterator<TT> | |
{ | |
BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator) | |
{ | |
i[n] = *i; // require element access and assignment | |
} | |
private: | |
TT i; | |
typename boost::detail::iterator_traits<TT>::difference_type n; | |
}; | |
//=========================================================================== | |
// Container s | |
BOOST_concept(Container,(C)) | |
: Assignable<C> | |
{ | |
typedef typename C::value_type value_type; | |
typedef typename C::difference_type difference_type; | |
typedef typename C::size_type size_type; | |
typedef typename C::const_reference const_reference; | |
typedef typename C::const_pointer const_pointer; | |
typedef typename C::const_iterator const_iterator; | |
BOOST_CONCEPT_USAGE(Container) | |
{ | |
BOOST_CONCEPT_ASSERT((InputIterator<const_iterator>)); | |
const_constraints(c); | |
} | |
private: | |
void const_constraints(const C& cc) { | |
i = cc.begin(); | |
i = cc.end(); | |
n = cc.size(); | |
n = cc.max_size(); | |
b = cc.empty(); | |
} | |
C c; | |
bool b; | |
const_iterator i; | |
size_type n; | |
}; | |
BOOST_concept(Mutable_Container,(C)) | |
: Container<C> | |
{ | |
typedef typename C::reference reference; | |
typedef typename C::iterator iterator; | |
typedef typename C::pointer pointer; | |
BOOST_CONCEPT_USAGE(Mutable_Container) | |
{ | |
BOOST_CONCEPT_ASSERT(( | |
Assignable<typename Mutable_Container::value_type>)); | |
BOOST_CONCEPT_ASSERT((InputIterator<iterator>)); | |
i = c.begin(); | |
i = c.end(); | |
c.swap(c2); | |
} | |
private: | |
iterator i; | |
C c, c2; | |
}; | |
BOOST_concept(ForwardContainer,(C)) | |
: Container<C> | |
{ | |
BOOST_CONCEPT_USAGE(ForwardContainer) | |
{ | |
BOOST_CONCEPT_ASSERT(( | |
ForwardIterator< | |
typename ForwardContainer::const_iterator | |
>)); | |
} | |
}; | |
BOOST_concept(Mutable_ForwardContainer,(C)) | |
: ForwardContainer<C> | |
, Mutable_Container<C> | |
{ | |
BOOST_CONCEPT_USAGE(Mutable_ForwardContainer) | |
{ | |
BOOST_CONCEPT_ASSERT(( | |
Mutable_ForwardIterator< | |
typename Mutable_ForwardContainer::iterator | |
>)); | |
} | |
}; | |
BOOST_concept(ReversibleContainer,(C)) | |
: ForwardContainer<C> | |
{ | |
typedef typename | |
C::const_reverse_iterator | |
const_reverse_iterator; | |
BOOST_CONCEPT_USAGE(ReversibleContainer) | |
{ | |
BOOST_CONCEPT_ASSERT(( | |
BidirectionalIterator< | |
typename ReversibleContainer::const_iterator>)); | |
BOOST_CONCEPT_ASSERT((BidirectionalIterator<const_reverse_iterator>)); | |
const_constraints(c); | |
} | |
private: | |
void const_constraints(const C& cc) | |
{ | |
const_reverse_iterator i = cc.rbegin(); | |
i = cc.rend(); | |
} | |
C c; | |
}; | |
BOOST_concept(Mutable_ReversibleContainer,(C)) | |
: Mutable_ForwardContainer<C> | |
, ReversibleContainer<C> | |
{ | |
typedef typename C::reverse_iterator reverse_iterator; | |
BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer) | |
{ | |
typedef typename Mutable_ForwardContainer<C>::iterator iterator; | |
BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<iterator>)); | |
BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator<reverse_iterator>)); | |
reverse_iterator i = c.rbegin(); | |
i = c.rend(); | |
} | |
private: | |
C c; | |
}; | |
BOOST_concept(RandomAccessContainer,(C)) | |
: ReversibleContainer<C> | |
{ | |
typedef typename C::size_type size_type; | |
typedef typename C::const_reference const_reference; | |
BOOST_CONCEPT_USAGE(RandomAccessContainer) | |
{ | |
BOOST_CONCEPT_ASSERT(( | |
RandomAccessIterator< | |
typename RandomAccessContainer::const_iterator | |
>)); | |
const_constraints(c); | |
} | |
private: | |
void const_constraints(const C& cc) | |
{ | |
const_reference r = cc[n]; | |
ignore_unused_variable_warning(r); | |
} | |
C c; | |
size_type n; | |
}; | |
BOOST_concept(Mutable_RandomAccessContainer,(C)) | |
: Mutable_ReversibleContainer<C> | |
, RandomAccessContainer<C> | |
{ | |
private: | |
typedef Mutable_RandomAccessContainer self; | |
public: | |
BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer) | |
{ | |
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::iterator>)); | |
BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator<typename self::reverse_iterator>)); | |
typename self::reference r = c[i]; | |
ignore_unused_variable_warning(r); | |
} | |
private: | |
typename Mutable_ReversibleContainer<C>::size_type i; | |
C c; | |
}; | |
// A Sequence is inherently mutable | |
BOOST_concept(Sequence,(S)) | |
: Mutable_ForwardContainer<S> | |
// Matt Austern's book puts DefaultConstructible here, the C++ | |
// standard places it in Container --JGS | |
// ... so why aren't we following the standard? --DWA | |
, DefaultConstructible<S> | |
{ | |
BOOST_CONCEPT_USAGE(Sequence) | |
{ | |
S | |
c(n), | |
c2(n, t), | |
c3(first, last); | |
c.insert(p, t); | |
c.insert(p, n, t); | |
c.insert(p, first, last); | |
c.erase(p); | |
c.erase(p, q); | |
typename Sequence::reference r = c.front(); | |
ignore_unused_variable_warning(c); | |
ignore_unused_variable_warning(c2); | |
ignore_unused_variable_warning(c3); | |
ignore_unused_variable_warning(r); | |
const_constraints(c); | |
} | |
private: | |
void const_constraints(const S& c) { | |
typename Sequence::const_reference r = c.front(); | |
ignore_unused_variable_warning(r); | |
} | |
typename S::value_type t; | |
typename S::size_type n; | |
typename S::value_type* first, *last; | |
typename S::iterator p, q; | |
}; | |
BOOST_concept(FrontInsertionSequence,(S)) | |
: Sequence<S> | |
{ | |
BOOST_CONCEPT_USAGE(FrontInsertionSequence) | |
{ | |
c.push_front(t); | |
c.pop_front(); | |
} | |
private: | |
S c; | |
typename S::value_type t; | |
}; | |
BOOST_concept(BackInsertionSequence,(S)) | |
: Sequence<S> | |
{ | |
BOOST_CONCEPT_USAGE(BackInsertionSequence) | |
{ | |
c.push_back(t); | |
c.pop_back(); | |
typename BackInsertionSequence::reference r = c.back(); | |
ignore_unused_variable_warning(r); | |
const_constraints(c); | |
} | |
private: | |
void const_constraints(const S& cc) { | |
typename BackInsertionSequence::const_reference | |
r = cc.back(); | |
ignore_unused_variable_warning(r); | |
}; | |
S c; | |
typename S::value_type t; | |
}; | |
BOOST_concept(AssociativeContainer,(C)) | |
: ForwardContainer<C> | |
, DefaultConstructible<C> | |
{ | |
typedef typename C::key_type key_type; | |
typedef typename C::key_compare key_compare; | |
typedef typename C::value_compare value_compare; | |
typedef typename C::iterator iterator; | |
BOOST_CONCEPT_USAGE(AssociativeContainer) | |
{ | |
i = c.find(k); | |
r = c.equal_range(k); | |
c.erase(k); | |
c.erase(i); | |
c.erase(r.first, r.second); | |
const_constraints(c); | |
BOOST_CONCEPT_ASSERT((BinaryPredicate<key_compare,key_type,key_type>)); | |
typedef typename AssociativeContainer::value_type value_type_; | |
BOOST_CONCEPT_ASSERT((BinaryPredicate<value_compare,value_type_,value_type_>)); | |
} | |
// Redundant with the base concept, but it helps below. | |
typedef typename C::const_iterator const_iterator; | |
private: | |
void const_constraints(const C& cc) | |
{ | |
ci = cc.find(k); | |
n = cc.count(k); | |
cr = cc.equal_range(k); | |
} | |
C c; | |
iterator i; | |
std::pair<iterator,iterator> r; | |
const_iterator ci; | |
std::pair<const_iterator,const_iterator> cr; | |
typename C::key_type k; | |
typename C::size_type n; | |
}; | |
BOOST_concept(UniqueAssociativeContainer,(C)) | |
: AssociativeContainer<C> | |
{ | |
BOOST_CONCEPT_USAGE(UniqueAssociativeContainer) | |
{ | |
C c(first, last); | |
pos_flag = c.insert(t); | |
c.insert(first, last); | |
ignore_unused_variable_warning(c); | |
} | |
private: | |
std::pair<typename C::iterator, bool> pos_flag; | |
typename C::value_type t; | |
typename C::value_type* first, *last; | |
}; | |
BOOST_concept(MultipleAssociativeContainer,(C)) | |
: AssociativeContainer<C> | |
{ | |
BOOST_CONCEPT_USAGE(MultipleAssociativeContainer) | |
{ | |
C c(first, last); | |
pos = c.insert(t); | |
c.insert(first, last); | |
ignore_unused_variable_warning(c); | |
ignore_unused_variable_warning(pos); | |
} | |
private: | |
typename C::iterator pos; | |
typename C::value_type t; | |
typename C::value_type* first, *last; | |
}; | |
BOOST_concept(SimpleAssociativeContainer,(C)) | |
: AssociativeContainer<C> | |
{ | |
BOOST_CONCEPT_USAGE(SimpleAssociativeContainer) | |
{ | |
typedef typename C::key_type key_type; | |
typedef typename C::value_type value_type; | |
BOOST_MPL_ASSERT((boost::is_same<key_type,value_type>)); | |
} | |
}; | |
BOOST_concept(PairAssociativeContainer,(C)) | |
: AssociativeContainer<C> | |
{ | |
BOOST_CONCEPT_USAGE(PairAssociativeContainer) | |
{ | |
typedef typename C::key_type key_type; | |
typedef typename C::value_type value_type; | |
typedef typename C::mapped_type mapped_type; | |
typedef std::pair<const key_type, mapped_type> required_value_type; | |
BOOST_MPL_ASSERT((boost::is_same<value_type,required_value_type>)); | |
} | |
}; | |
BOOST_concept(SortedAssociativeContainer,(C)) | |
: AssociativeContainer<C> | |
, ReversibleContainer<C> | |
{ | |
BOOST_CONCEPT_USAGE(SortedAssociativeContainer) | |
{ | |
C | |
c(kc), | |
c2(first, last), | |
c3(first, last, kc); | |
p = c.upper_bound(k); | |
p = c.lower_bound(k); | |
r = c.equal_range(k); | |
c.insert(p, t); | |
ignore_unused_variable_warning(c); | |
ignore_unused_variable_warning(c2); | |
ignore_unused_variable_warning(c3); | |
const_constraints(c); | |
} | |
void const_constraints(const C& c) | |
{ | |
kc = c.key_comp(); | |
vc = c.value_comp(); | |
cp = c.upper_bound(k); | |
cp = c.lower_bound(k); | |
cr = c.equal_range(k); | |
} | |
private: | |
typename C::key_compare kc; | |
typename C::value_compare vc; | |
typename C::value_type t; | |
typename C::key_type k; | |
typedef typename C::iterator iterator; | |
typedef typename C::const_iterator const_iterator; | |
typedef SortedAssociativeContainer self; | |
iterator p; | |
const_iterator cp; | |
std::pair<typename self::iterator,typename self::iterator> r; | |
std::pair<typename self::const_iterator,typename self::const_iterator> cr; | |
typename C::value_type* first, *last; | |
}; | |
// HashedAssociativeContainer | |
BOOST_concept(Collection,(C)) | |
{ | |
BOOST_CONCEPT_USAGE(Collection) | |
{ | |
boost::function_requires<boost::InputIteratorConcept<iterator> >(); | |
boost::function_requires<boost::InputIteratorConcept<const_iterator> >(); | |
boost::function_requires<boost::CopyConstructibleConcept<value_type> >(); | |
const_constraints(c); | |
i = c.begin(); | |
i = c.end(); | |
c.swap(c); | |
} | |
void const_constraints(const C& c) { | |
ci = c.begin(); | |
ci = c.end(); | |
n = c.size(); | |
b = c.empty(); | |
} | |
private: | |
typedef typename C::value_type value_type; | |
typedef typename C::iterator iterator; | |
typedef typename C::const_iterator const_iterator; | |
typedef typename C::reference reference; | |
typedef typename C::const_reference const_reference; | |
// typedef typename C::pointer pointer; | |
typedef typename C::difference_type difference_type; | |
typedef typename C::size_type size_type; | |
C c; | |
bool b; | |
iterator i; | |
const_iterator ci; | |
size_type n; | |
}; | |
} // namespace boost | |
# include <boost/concept/detail/concept_undef.hpp> | |
#endif // BOOST_CONCEPT_CHECKS_HPP | |