diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 8b090d0..eaa4ba0 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -13,24 +13,23 @@ // See http://www.boost.org/libs/concept_check for documentation. #ifndef BOOST_CONCEPT_CHECKS_HPP -#define BOOST_CONCEPT_CHECKS_HPP +# define BOOST_CONCEPT_CHECKS_HPP -#include -#include -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include - -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__BORLANDC__) -#define BOOST_FPTR -#else -#define BOOST_FPTR & -#endif - -namespace boost { +namespace boost +{ /* "inline" is used for ignore_unused_variable_warning() @@ -38,168 +37,156 @@ namespace boost { overhead with g++. */ -template inline void ignore_unused_variable_warning(const T&) { } +# if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ + && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x543)) + namespace concept_checking + { + template + void* failed(BOOST_EXPLICIT_TEMPLATE_TYPE(Model)) + { return new ((void*)0) Model; } + + template struct instantiate; + } + + template + struct concept_check + { + typedef typename boost::parameter::aux::unaryfunptr_arg_type::type model; + typedef concept_checking::instantiate > type; + + enum { instantiate = 1 }; + }; -// the unused, defaulted parameter is a workaround for MSVC and Compaq C++ -template -inline void function_requires(mpl::identity* = 0) -{ -#if !defined(NDEBUG) - void (Concept::*x)() = BOOST_FPTR Concept::constraints; - ignore_unused_variable_warning(x); -#endif -} +# else + namespace concept_checking + { + template + struct test + { + static void inline failed() { new ((void*)0) T; } + }; -#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ - typedef void (ns::concept ::* func##type_var##concept)(); \ - template \ - struct concept_checking_##type_var##concept { }; \ - typedef concept_checking_##type_var##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##type_var##concept + template inline void instantiate(T const&) {} + } -#define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ - typedef void (ns::concept ::* \ - func##type_var1##type_var2##concept)(); \ - template \ - struct concept_checking_##type_var1##type_var2##concept { }; \ - typedef concept_checking_##type_var1##type_var2##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##type_var1##type_var2##concept + template + struct concept_check + { + typedef typename boost::parameter::aux::unaryfunptr_arg_type::type model; + +# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // This occasionally causes ICE with vc6, and in-class checks + // don't work with that compiler anyway, and if you want the + // in-function checks to work you have to use + // function_requires<>, so disabling it does no harm. + virtual void failed() { new ((void*)0) model; } +# endif + + enum { instantiate = 1 }; + }; +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); + // + // This macro works everywhere except vc-6.0 and Borland. On those + // compilers it will be innocuous but will never cause a compilation + // error. Concept checks at class level seem to be impossible on + // those compilers. If you want to see errors at function level, + // you have to use the old boost_function_requires idiom, which + // works everywhere. +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + typedef int BOOST_PP_CAT(boost_concept_check,__LINE__)[ \ + ::boost::concept_check< void(*)ModelInParens >::instantiate \ + ] -#define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ - typedef void (ns::concept ::* \ - func##tv1##tv2##tv3##concept)(); \ - template \ - struct concept_checking_##tv1##tv2##tv3##concept { }; \ - typedef concept_checking_##tv1##tv2##tv3##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##tv1##tv2##tv3##concept + // + // Backward compatibility + // + + template + inline void function_requires(BOOST_EXPLICIT_TEMPLATE_TYPE(Model)) + { +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x543)) + concept_checking::instantiate(&concept_checking::test::failed); +# else + BOOST_CONCEPT_ASSERT((Model)); +# endif + } -#define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ - typedef void (ns::concept ::* \ - func##tv1##tv2##tv3##tv4##concept)(); \ - template \ - struct concept_checking_##tv1##tv2##tv3##tv4##concept { }; \ - typedef concept_checking_##tv1##tv2##tv3##tv4##concept< \ - BOOST_FPTR ns::concept::constraints> \ - concept_checking_typedef_##tv1##tv2##tv3##tv4##concept + template inline void ignore_unused_variable_warning(T const&) {} + +# define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) -// NOTE: The BOOST_CLASS_REQUIRES (with an 'S' at the end) is deprecated. +# define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) -// The BOOST_CLASS_REQUIRES macros use function pointers as -// template parameters, which VC++ does not support. +# define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) -#if defined(BOOST_NO_FUNCTION_PTR_TEMPLATE_PARAMETERS) - -#define BOOST_CLASS_REQUIRES(type_var, concept) -#define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept) -#define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept) -#define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept) - -#else - -#define BOOST_CLASS_REQUIRES(type_var, concept) \ - typedef void (concept ::* func##type_var##concept)(); \ - template \ - struct concept_checking_##type_var##concept { }; \ - typedef concept_checking_##type_var##concept< \ - BOOST_FPTR concept ::constraints> \ - concept_checking_typedef_##type_var##concept - -#define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept) \ - typedef void (concept ::* func##type_var1##type_var2##concept)(); \ - template \ - struct concept_checking_##type_var1##type_var2##concept { }; \ - typedef concept_checking_##type_var1##type_var2##concept< \ - BOOST_FPTR concept ::constraints> \ - concept_checking_typedef_##type_var1##type_var2##concept - -#define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept) \ - typedef void (concept ::* func##type_var1##type_var2##type_var3##concept)(); \ - template \ - struct concept_checking_##type_var1##type_var2##type_var3##concept { }; \ - typedef concept_checking_##type_var1##type_var2##type_var3##concept< \ - BOOST_FPTR concept ::constraints> \ - concept_checking_typedef_##type_var1##type_var2##type_var3##concept - -#define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept) \ - typedef void (concept ::* func##type_var1##type_var2##type_var3##type_var4##concept)(); \ - template \ - struct concept_checking_##type_var1##type_var2##type_var3##type_var4##concept { }; \ - typedef concept_checking_##type_var1##type_var2##type_var3##type_var4##concept< \ - BOOST_FPTR concept ::constraints> \ - concept_checking_typedef_##type_var1##type_var2##type_var3##type_var4##concept - - -#endif - -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct require_same { }; - -template -struct require_same { typedef T type; }; -#else -// This version does not perform checking, but will not do any harm. -template -struct require_same { typedef T type; }; -#endif +# define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) template struct IntegerConcept { - void constraints() { + IntegerConcept() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION x.error_type_must_be_an_integer_type(); #endif } - T x; + private: + static T x; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template <> struct IntegerConcept { void constraints() {} }; - template <> struct IntegerConcept { void constraints() {} }; - template <> struct IntegerConcept { void constraints() {} }; - template <> struct IntegerConcept { void constraints() {} }; - template <> struct IntegerConcept { void constraints() {} }; - template <> struct IntegerConcept { void constraints() {} }; + template <> struct IntegerConcept { IntegerConcept() {} }; + template <> struct IntegerConcept { IntegerConcept() {} }; + template <> struct IntegerConcept { IntegerConcept() {} }; + template <> struct IntegerConcept { IntegerConcept() {} }; + template <> struct IntegerConcept { IntegerConcept() {} }; + template <> struct IntegerConcept { IntegerConcept() {} }; // etc. #endif template struct SignedIntegerConcept { - void constraints() { + SignedIntegerConcept() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION x.error_type_must_be_a_signed_integer_type(); #endif } - T x; + private: + static T x; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template <> struct SignedIntegerConcept { void constraints() {} }; - template <> struct SignedIntegerConcept { void constraints() {} }; - template <> struct SignedIntegerConcept { void constraints() {} }; + template <> struct SignedIntegerConcept { SignedIntegerConcept() {} }; + template <> struct SignedIntegerConcept { SignedIntegerConcept() {} }; + template <> struct SignedIntegerConcept { SignedIntegerConcept() {} }; # if defined(BOOST_HAS_LONG_LONG) - template <> struct SignedIntegerConcept< ::boost::long_long_type> { void constraints() {} }; + template <> struct SignedIntegerConcept< ::boost::long_long_type> { SignedIntegerConcept() {} }; # endif // etc. #endif template struct UnsignedIntegerConcept { - void constraints() { + UnsignedIntegerConcept() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION x.error_type_must_be_an_unsigned_integer_type(); #endif } - T x; + private: + static T x; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template <> struct UnsignedIntegerConcept - { void constraints() {} }; + { UnsignedIntegerConcept() {} }; template <> struct UnsignedIntegerConcept - { void constraints() {} }; + { UnsignedIntegerConcept() {} }; template <> struct UnsignedIntegerConcept - { void constraints() {} }; + { UnsignedIntegerConcept() {} }; // etc. #endif @@ -209,7 +196,7 @@ struct require_same { typedef T type; }; template struct DefaultConstructibleConcept { - void constraints() { + DefaultConstructibleConcept() { TT a; // require default constructor ignore_unused_variable_warning(a); } @@ -218,43 +205,46 @@ struct require_same { typedef T type; }; template struct AssignableConcept { - void constraints() { + AssignableConcept() { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator #endif const_constraints(a); } + private: void const_constraints(const TT& b) { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = b; // const required for argument to assignment #endif } - TT a; + private: + static TT a; }; template struct CopyConstructibleConcept { - void constraints() { + CopyConstructibleConcept() { 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; + static TT b; }; // The SGI STL version of Assignable requires copy constructor and operator= template struct SGIAssignableConcept { - void constraints() { + SGIAssignableConcept() { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator @@ -262,6 +252,7 @@ struct require_same { typedef T type; }; const_constraints(a); ignore_unused_variable_warning(b); } + private: void const_constraints(const TT& b) { TT c(b); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL @@ -269,17 +260,18 @@ struct require_same { typedef T type; }; #endif ignore_unused_variable_warning(c); } - TT a; + static TT a; }; template struct ConvertibleConcept { - void constraints() { + ConvertibleConcept() { Y y = x; ignore_unused_variable_warning(y); } - X x; + private: + static X x; }; // The C++ standard requirements for many concepts talk about return @@ -300,56 +292,61 @@ struct require_same { typedef T type; }; template struct EqualityComparableConcept { - void constraints() { + EqualityComparableConcept() { require_boolean_expr(a == b); require_boolean_expr(a != b); } - TT a, b; + private: + static TT a, b; }; template struct LessThanComparableConcept { - void constraints() { + LessThanComparableConcept() { require_boolean_expr(a < b); } - TT a, b; + private: + static TT a, b; }; // This is equivalent to SGI STL's LessThanComparable. template struct ComparableConcept { - void constraints() { + ComparableConcept() { require_boolean_expr(a < b); require_boolean_expr(a > b); require_boolean_expr(a <= b); require_boolean_expr(a >= b); } - TT a, b; + private: + static TT a, b; }; -#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ - template \ - struct NAME { \ - void constraints() { (void)constraints_(); } \ - bool constraints_() { \ - return a OP b; \ - } \ - First a; \ - Second b; \ - } +#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ + template \ + struct NAME { \ + NAME() { (void)constraints_(); } \ + private: \ + bool constraints_() { \ + return a OP b; \ + } \ + static First a; \ + static Second b; \ + } -#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ - template \ - struct NAME { \ - void constraints() { (void)constraints_(); } \ - Ret constraints_() { \ - return a OP b; \ - } \ - First a; \ - Second b; \ - } +#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ + template \ + struct NAME { \ + NAME() { (void)constraints_(); } \ + private: \ + Ret constraints_() { \ + return a OP b; \ + } \ + static First a; \ + static Second b; \ + } BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOpConcept); @@ -370,11 +367,12 @@ struct require_same { typedef T type; }; template struct GeneratorConcept { - void constraints() { + GeneratorConcept() { const Return& r = f(); // require operator() member function ignore_unused_variable_warning(r); } - Func f; + private: + static Func f; }; @@ -382,292 +380,308 @@ struct require_same { typedef T type; }; template struct GeneratorConcept { - void constraints() { + GeneratorConcept() { f(); // require operator() member function } - Func f; + private: + static Func f; }; #endif template struct UnaryFunctionConcept { - // required in case any of our template args are const-qualified: - UnaryFunctionConcept(); - - void constraints() { + UnaryFunctionConcept() { r = f(arg); // require operator() } - Func f; - Arg arg; - Return r; + private: + static Func f; + static Arg arg; + static Return r; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct UnaryFunctionConcept { - void constraints() { + UnaryFunctionConcept() { f(arg); // require operator() } - Func f; - Arg arg; + private: + static Func f; + static Arg arg; }; #endif template struct BinaryFunctionConcept { - void constraints() { + BinaryFunctionConcept() { r = f(first, second); // require operator() } - Func f; - First first; - Second second; - Return r; + private: + static Func f; + static First first; + static Second second; + static Return r; }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct BinaryFunctionConcept { - void constraints() { + BinaryFunctionConcept() { f(first, second); // require operator() } - Func f; - First first; - Second second; + private: + static Func f; + static First first; + static Second second; }; #endif template struct UnaryPredicateConcept { - void constraints() { + UnaryPredicateConcept() { require_boolean_expr(f(arg)); // require operator() returning bool } - Func f; - Arg arg; + private: + static Func f; + static Arg arg; }; template struct BinaryPredicateConcept { - void constraints() { + BinaryPredicateConcept() { require_boolean_expr(f(a, b)); // require operator() returning bool } - Func f; - First a; - Second b; + private: + static Func f; + static First a; + static Second b; }; // use this when functor is used inside a container class like std::set template - struct Const_BinaryPredicateConcept { - void constraints() { + struct Const_BinaryPredicateConcept + : BinaryPredicateConcept + { + Const_BinaryPredicateConcept() { const_constraints(f); } + private: void const_constraints(const Func& fun) { - function_requires >(); // operator() must be a const member function require_boolean_expr(fun(a, b)); } - Func f; - First a; - Second b; + static Func f; + static First a; + static Second b; }; template struct AdaptableGeneratorConcept + : GeneratorConcept { - void constraints() { typedef typename Func::result_type result_type; - BOOST_STATIC_ASSERT((is_convertible::value)); - function_requires< GeneratorConcept >(); - } + + AdaptableGeneratorConcept() + { + BOOST_MPL_ASSERT((is_convertible)); + } }; template struct AdaptableUnaryFunctionConcept + : UnaryFunctionConcept { - void constraints() { typedef typename Func::argument_type argument_type; typedef typename Func::result_type result_type; - BOOST_STATIC_ASSERT((is_convertible::value)); - BOOST_STATIC_ASSERT((is_convertible::value)); - function_requires< UnaryFunctionConcept >(); - } + + AdaptableUnaryFunctionConcept() + { + BOOST_MPL_ASSERT((is_convertible)); + BOOST_MPL_ASSERT((is_convertible)); + } }; template struct AdaptableBinaryFunctionConcept + : BinaryFunctionConcept< + Func + , typename Func::result_type + , typename Func::first_argument_type + , typename Func::second_argument_type + > { - void constraints() { 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; - BOOST_STATIC_ASSERT((is_convertible::value)); - BOOST_STATIC_ASSERT((is_convertible::value)); - BOOST_STATIC_ASSERT((is_convertible::value)); - function_requires< BinaryFunctionConcept >(); - } + + AdaptableBinaryFunctionConcept() + { + BOOST_MPL_ASSERT((is_convertible)); + BOOST_MPL_ASSERT((is_convertible)); + BOOST_MPL_ASSERT((is_convertible)); + } }; template struct AdaptablePredicateConcept - { - void constraints() { - function_requires< UnaryPredicateConcept >(); - function_requires< AdaptableUnaryFunctionConcept >(); - } - }; + : UnaryPredicateConcept + , AdaptableUnaryFunctionConcept + {}; template struct AdaptableBinaryPredicateConcept - { - void constraints() { - function_requires< BinaryPredicateConcept >(); - function_requires< AdaptableBinaryFunctionConcept >(); - } - }; + : BinaryPredicateConcept + , AdaptableBinaryFunctionConcept + {}; //=========================================================================== // Iterator Concepts template struct InputIteratorConcept + : AssignableConcept + , EqualityComparableConcept { - void constraints() { - function_requires< AssignableConcept >(); - function_requires< EqualityComparableConcept >(); - TT j(i); - (void)*i; // require dereference operator -#ifndef BOOST_NO_STD_ITERATOR_TRAITS // require iterator_traits typedef's - typedef typename std::iterator_traits::difference_type D; + typedef typename boost::detail::iterator_traits::difference_type difference_type; // Hmm, the following is a bit fragile - //function_requires< SignedIntegerConcept >(); - typedef typename std::iterator_traits::reference R; - typedef typename std::iterator_traits::pointer P; - typedef typename std::iterator_traits::iterator_category C; - function_requires< ConvertibleConcept >(); -#endif - ++j; // require preincrement operator - i++; // require postincrement operator - } - TT i; + typedef typename boost::detail::iterator_traits::reference reference; + typedef typename boost::detail::iterator_traits::pointer pointer; + typedef typename boost::detail::iterator_traits::iterator_category iterator_category; + + InputIteratorConcept() + { + SignedIntegerConcept(); + ConvertibleConcept(); + + TT j(i); + (void)*i; // require dereference operator + ++j; // require preincrement operator + i++; // require postincrement operator + } + private: + static TT i; }; template struct OutputIteratorConcept + : AssignableConcept { - void constraints() { - function_requires< AssignableConcept >(); + OutputIteratorConcept() { + ++i; // require preincrement operator i++; // require postincrement operator *i++ = t; // require postincrement and assignment } - TT i, j; - ValueT t; + private: + static TT i, j; + static ValueT t; }; template struct ForwardIteratorConcept + : InputIteratorConcept { - void constraints() { - function_requires< InputIteratorConcept >(); -#ifndef BOOST_NO_STD_ITERATOR_TRAITS - typedef typename std::iterator_traits::iterator_category C; - function_requires< ConvertibleConcept >(); - typedef typename std::iterator_traits::reference reference; - reference r = *i; - ignore_unused_variable_warning(r); -#endif - } - TT i; + ForwardIteratorConcept() + { + ConvertibleConcept< + BOOST_DEDUCED_TYPENAME ForwardIteratorConcept::iterator_category + , std::forward_iterator_tag + >(); + + typename InputIteratorConcept::reference r = *i; + ignore_unused_variable_warning(r); + } + + private: + static TT i; }; template struct Mutable_ForwardIteratorConcept + : ForwardIteratorConcept { - void constraints() { - function_requires< ForwardIteratorConcept >(); - *i++ = *i; // require postincrement and assignment - } - TT i; + Mutable_ForwardIteratorConcept() { + *i++ = *i; // require postincrement and assignment + } + private: + static TT i; }; template struct BidirectionalIteratorConcept + : ForwardIteratorConcept { - void constraints() { - function_requires< ForwardIteratorConcept >(); -#ifndef BOOST_NO_STD_ITERATOR_TRAITS - typedef typename std::iterator_traits::iterator_category C; - function_requires< ConvertibleConcept >(); -#endif - --i; // require predecrement operator - i--; // require postdecrement operator - } - TT i; + BidirectionalIteratorConcept() + { + ConvertibleConcept< + BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::iterator_category + , std::bidirectional_iterator_tag + >(); + + --i; // require predecrement operator + i--; // require postdecrement operator + } + private: + static TT i; }; template struct Mutable_BidirectionalIteratorConcept + : BidirectionalIteratorConcept + , Mutable_ForwardIteratorConcept { - void constraints() { - function_requires< BidirectionalIteratorConcept >(); - function_requires< Mutable_ForwardIteratorConcept >(); - *i-- = *i; // require postdecrement and assignment - } - TT i; + Mutable_BidirectionalIteratorConcept() + { + *i-- = *i; // require postdecrement and assignment + } + private: + static TT i; }; template struct RandomAccessIteratorConcept + : BidirectionalIteratorConcept + , ComparableConcept { - void constraints() { - function_requires< BidirectionalIteratorConcept >(); - function_requires< ComparableConcept >(); -#ifndef BOOST_NO_STD_ITERATOR_TRAITS - typedef typename std::iterator_traits::iterator_category C; - function_requires< ConvertibleConcept< C, - std::random_access_iterator_tag> >(); - typedef typename std::iterator_traits::reference R; -#endif + RandomAccessIteratorConcept() + { + ConvertibleConcept< + BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::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 - } - TT a, b; - TT i, j; -#ifndef BOOST_NO_STD_ITERATOR_TRAITS - typename std::iterator_traits::difference_type n; -#else - std::ptrdiff_t n; -#endif + 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: + static TT a, b; + static TT i, j; + typename boost::detail::iterator_traits::difference_type n; }; template struct Mutable_RandomAccessIteratorConcept + : RandomAccessIteratorConcept + , Mutable_BidirectionalIteratorConcept { - void constraints() { - function_requires< RandomAccessIteratorConcept >(); - function_requires< Mutable_BidirectionalIteratorConcept >(); + Mutable_RandomAccessIteratorConcept() { i[n] = *i; // require element access and assignment } - TT i; -#ifndef BOOST_NO_STD_ITERATOR_TRAITS - typename std::iterator_traits::difference_type n; -#else - std::ptrdiff_t n; -#endif + private: + static TT i; + typename boost::detail::iterator_traits::difference_type n; }; //=========================================================================== @@ -675,6 +689,7 @@ struct require_same { typedef T type; }; template struct ContainerConcept + : AssignableConcept { typedef typename Container::value_type value_type; typedef typename Container::difference_type difference_type; @@ -683,369 +698,397 @@ struct require_same { typedef T type; }; typedef typename Container::const_pointer const_pointer; typedef typename Container::const_iterator const_iterator; - void constraints() { - function_requires< InputIteratorConcept >(); - function_requires< AssignableConcept >(); - const_constraints(c); - } - void const_constraints(const Container& cc) { - i = cc.begin(); - i = cc.end(); - n = cc.size(); - n = cc.max_size(); - b = cc.empty(); - } - Container c; - bool b; - const_iterator i; - size_type n; + ContainerConcept() + { + InputIteratorConcept(); + const_constraints(c); + } + + private: + void const_constraints(const Container& cc) { + i = cc.begin(); + i = cc.end(); + n = cc.size(); + n = cc.max_size(); + b = cc.empty(); + } + static Container c; + static bool b; + static const_iterator i; + static size_type n; }; template struct Mutable_ContainerConcept + : ContainerConcept { - typedef typename Container::value_type value_type; - typedef typename Container::reference reference; - typedef typename Container::iterator iterator; - typedef typename Container::pointer pointer; + typedef typename Container::reference reference; + typedef typename Container::iterator iterator; + typedef typename Container::pointer pointer; - void constraints() { - function_requires< ContainerConcept >(); - function_requires< AssignableConcept >(); - function_requires< InputIteratorConcept >(); - - i = c.begin(); - i = c.end(); - c.swap(c2); - } - iterator i; - Container c, c2; + Mutable_ContainerConcept() + { + AssignableConcept(); + InputIteratorConcept(); + + i = c.begin(); + i = c.end(); + c.swap(c2); + } + + private: + static iterator i; + static Container c, c2; }; template struct ForwardContainerConcept + : ContainerConcept { - void constraints() { - function_requires< ContainerConcept >(); - typedef typename ForwardContainer::const_iterator const_iterator; - function_requires< ForwardIteratorConcept >(); - } + ForwardContainerConcept() + { + ForwardIteratorConcept(); + } }; template struct Mutable_ForwardContainerConcept + : ForwardContainerConcept + , Mutable_ContainerConcept { - void constraints() { - function_requires< ForwardContainerConcept >(); - function_requires< Mutable_ContainerConcept >(); - typedef typename ForwardContainer::iterator iterator; - function_requires< Mutable_ForwardIteratorConcept >(); - } + Mutable_ForwardContainerConcept() + { + Mutable_ForwardIteratorConcept< + typename Mutable_ForwardContainerConcept::iterator + >(); + } }; template struct ReversibleContainerConcept + : ForwardContainerConcept { - typedef typename ReversibleContainer::const_iterator const_iterator; - typedef typename ReversibleContainer::const_reverse_iterator + typedef typename + ReversibleContainer::const_reverse_iterator const_reverse_iterator; - void constraints() { - function_requires< ForwardContainerConcept >(); - function_requires< BidirectionalIteratorConcept >(); - function_requires< - BidirectionalIteratorConcept >(); - const_constraints(c); - } - void const_constraints(const ReversibleContainer& cc) { - const_reverse_iterator i = cc.rbegin(); - i = cc.rend(); - } - ReversibleContainer c; + ReversibleContainerConcept() + { + BidirectionalIteratorConcept(); + BidirectionalIteratorConcept(); + const_constraints(c); + } + private: + void const_constraints(const ReversibleContainer& cc) + { + const_reverse_iterator i = cc.rbegin(); + i = cc.rend(); + } + static ReversibleContainer c; }; template struct Mutable_ReversibleContainerConcept + : Mutable_ForwardContainerConcept + , ReversibleContainerConcept { - typedef typename ReversibleContainer::iterator iterator; - typedef typename ReversibleContainer::reverse_iterator reverse_iterator; + typedef typename ReversibleContainer::iterator iterator; + typedef typename ReversibleContainer::reverse_iterator reverse_iterator; - void constraints() { - function_requires< ReversibleContainerConcept >(); - function_requires< - Mutable_ForwardContainerConcept >(); - function_requires< Mutable_BidirectionalIteratorConcept >(); - function_requires< - Mutable_BidirectionalIteratorConcept >(); - - reverse_iterator i = c.rbegin(); - i = c.rend(); - } - ReversibleContainer c; + Mutable_ReversibleContainerConcept() + { + Mutable_BidirectionalIteratorConcept(); + Mutable_BidirectionalIteratorConcept(); + reverse_iterator i = c.rbegin(); + i = c.rend(); + } + private: + static ReversibleContainer c; }; template struct RandomAccessContainerConcept + : ReversibleContainerConcept { - typedef typename RandomAccessContainer::size_type size_type; - typedef typename RandomAccessContainer::const_reference const_reference; - typedef typename RandomAccessContainer::const_iterator const_iterator; - typedef typename RandomAccessContainer::const_reverse_iterator - const_reverse_iterator; + typedef typename RandomAccessContainer::size_type size_type; + typedef typename RandomAccessContainer::const_reference const_reference; - void constraints() { - function_requires< ReversibleContainerConcept >(); - function_requires< RandomAccessIteratorConcept >(); - function_requires< - RandomAccessIteratorConcept >(); - - const_constraints(c); - } - void const_constraints(const RandomAccessContainer& cc) { - const_reference r = cc[n]; - ignore_unused_variable_warning(r); - } - RandomAccessContainer c; - size_type n; + RandomAccessContainerConcept() + { + RandomAccessIteratorConcept< + typename RandomAccessContainerConcept::const_iterator + >(); + + const_constraints(c); + } + private: + void const_constraints(const RandomAccessContainer& cc) + { + const_reference r = cc[n]; + ignore_unused_variable_warning(r); + } + + static RandomAccessContainer c; + static size_type n; }; template struct Mutable_RandomAccessContainerConcept + : Mutable_ReversibleContainerConcept + , RandomAccessContainerConcept { - typedef typename RandomAccessContainer::size_type size_type; - typedef typename RandomAccessContainer::reference reference; - typedef typename RandomAccessContainer::iterator iterator; - typedef typename RandomAccessContainer::reverse_iterator reverse_iterator; - - void constraints() { - function_requires< - RandomAccessContainerConcept >(); - function_requires< - Mutable_ReversibleContainerConcept >(); - function_requires< Mutable_RandomAccessIteratorConcept >(); - function_requires< - Mutable_RandomAccessIteratorConcept >(); - - reference r = c[i]; - ignore_unused_variable_warning(r); - } - size_type i; - RandomAccessContainer c; + private: + typedef Mutable_RandomAccessContainerConcept self; + public: + Mutable_RandomAccessContainerConcept() + { + Mutable_RandomAccessIteratorConcept(); + Mutable_RandomAccessIteratorConcept(); + + typename self::reference r = c[i]; + ignore_unused_variable_warning(r); + } + + private: + static typename Mutable_ReversibleContainerConcept::size_type i; + static RandomAccessContainer c; }; // A Sequence is inherently mutable template struct SequenceConcept - { - - typedef typename Sequence::reference reference; - typedef typename Sequence::const_reference const_reference; - - void constraints() { + : Mutable_ForwardContainerConcept // Matt Austern's book puts DefaultConstructible here, the C++ - // standard places it in Container - // function_requires< DefaultConstructible >(); - function_requires< Mutable_ForwardContainerConcept >(); - function_requires< DefaultConstructibleConcept >(); + // standard places it in Container --JGS + // ... so why aren't we following the standard? --DWA + , DefaultConstructibleConcept + { + SequenceConcept() + { + Sequence + c(n), + c2(n, t), + c3(first, last); - Sequence - c(n), - c2(n, t), - c3(first, last); + c.insert(p, t); + c.insert(p, n, t); + c.insert(p, first, last); - c.insert(p, t); - c.insert(p, n, t); - c.insert(p, first, last); + c.erase(p); + c.erase(p, q); - c.erase(p); - c.erase(p, q); + typename SequenceConcept::reference r = c.front(); - 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); - } - void const_constraints(const Sequence& c) { - const_reference r = c.front(); - ignore_unused_variable_warning(r); - } - typename Sequence::value_type t; - typename Sequence::size_type n; - typename Sequence::value_type* first, *last; - typename Sequence::iterator p, q; + 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 Sequence& c) { + typename SequenceConcept::const_reference r = c.front(); + ignore_unused_variable_warning(r); + } + + static typename Sequence::value_type t; + static typename Sequence::size_type n; + static typename Sequence::value_type* first, *last; + static typename Sequence::iterator p, q; }; template struct FrontInsertionSequenceConcept + : SequenceConcept { - void constraints() { - function_requires< SequenceConcept >(); - - c.push_front(t); - c.pop_front(); - } - FrontInsertionSequence c; - typename FrontInsertionSequence::value_type t; + FrontInsertionSequenceConcept() + { + c.push_front(t); + c.pop_front(); + } + private: + static FrontInsertionSequence c; + static typename FrontInsertionSequence::value_type t; }; template struct BackInsertionSequenceConcept + : SequenceConcept { - typedef typename BackInsertionSequence::reference reference; - typedef typename BackInsertionSequence::const_reference const_reference; - - void constraints() { - function_requires< SequenceConcept >(); - - c.push_back(t); - c.pop_back(); - reference r = c.back(); - ignore_unused_variable_warning(r); - } - void const_constraints(const BackInsertionSequence& cc) { - const_reference r = cc.back(); - ignore_unused_variable_warning(r); - }; - BackInsertionSequence c; - typename BackInsertionSequence::value_type t; + BackInsertionSequenceConcept() + { + c.push_back(t); + c.pop_back(); + typename BackInsertionSequenceConcept::reference r = c.back(); + ignore_unused_variable_warning(r); + const_constraints(c); + } + private: + void const_constraints(const BackInsertionSequence& cc) { + typename BackInsertionSequenceConcept::const_reference + r = cc.back(); + ignore_unused_variable_warning(r); + }; + static BackInsertionSequence c; + static typename BackInsertionSequence::value_type t; }; template struct AssociativeContainerConcept + : ForwardContainerConcept + , DefaultConstructibleConcept { - void constraints() { - function_requires< ForwardContainerConcept >(); - function_requires< DefaultConstructibleConcept >(); - - i = c.find(k); - r = c.equal_range(k); - c.erase(k); - c.erase(i); - c.erase(r.first, r.second); - const_constraints(c); - } - void const_constraints(const AssociativeContainer& cc) { - ci = cc.find(k); - n = cc.count(k); - cr = cc.equal_range(k); - } - typedef typename AssociativeContainer::iterator iterator; - typedef typename AssociativeContainer::const_iterator const_iterator; + typedef typename AssociativeContainer::key_type key_type; + typedef typename AssociativeContainer::key_compare key_compare; + typedef typename AssociativeContainer::value_compare value_compare; + typedef typename AssociativeContainer::iterator iterator; - AssociativeContainer c; - iterator i; - std::pair r; - const_iterator ci; - std::pair cr; - typename AssociativeContainer::key_type k; - typename AssociativeContainer::size_type n; + AssociativeContainerConcept() + { + i = c.find(k); + r = c.equal_range(k); + c.erase(k); + c.erase(i); + c.erase(r.first, r.second); + const_constraints(c); + BinaryPredicateConcept(); + + typedef typename AssociativeContainerConcept::value_type value_type; + BinaryPredicateConcept(); + } + + // Redundant with the base concept, but it helps below. + typedef typename AssociativeContainer::const_iterator const_iterator; + private: + void const_constraints(const AssociativeContainer& cc) + { + ci = cc.find(k); + n = cc.count(k); + cr = cc.equal_range(k); + } + + static AssociativeContainer c; + static iterator i; + static std::pair r; + static const_iterator ci; + static std::pair cr; + static typename AssociativeContainer::key_type k; + static typename AssociativeContainer::size_type n; }; template struct UniqueAssociativeContainerConcept + : AssociativeContainerConcept { - void constraints() { - function_requires< AssociativeContainerConcept >(); - - UniqueAssociativeContainer c(first, last); + UniqueAssociativeContainerConcept() + { + UniqueAssociativeContainer c(first, last); - pos_flag = c.insert(t); - c.insert(first, last); + pos_flag = c.insert(t); + c.insert(first, last); - ignore_unused_variable_warning(c); - } - std::pair pos_flag; - typename UniqueAssociativeContainer::value_type t; - typename UniqueAssociativeContainer::value_type* first, *last; + ignore_unused_variable_warning(c); + } + private: + static std::pair pos_flag; + static typename UniqueAssociativeContainer::value_type t; + static typename UniqueAssociativeContainer::value_type* first, *last; }; template struct MultipleAssociativeContainerConcept + : AssociativeContainerConcept { - void constraints() { - function_requires< AssociativeContainerConcept >(); - - MultipleAssociativeContainer c(first, last); + MultipleAssociativeContainerConcept() + { + MultipleAssociativeContainer c(first, last); - pos = c.insert(t); - c.insert(first, last); + pos = c.insert(t); + c.insert(first, last); - ignore_unused_variable_warning(c); - ignore_unused_variable_warning(pos); - } - typename MultipleAssociativeContainer::iterator pos; - typename MultipleAssociativeContainer::value_type t; - typename MultipleAssociativeContainer::value_type* first, *last; + ignore_unused_variable_warning(c); + ignore_unused_variable_warning(pos); + } + private: + static typename MultipleAssociativeContainer::iterator pos; + static typename MultipleAssociativeContainer::value_type t; + static typename MultipleAssociativeContainer::value_type* first, *last; }; template struct SimpleAssociativeContainerConcept + : AssociativeContainerConcept { - void constraints() { - function_requires< AssociativeContainerConcept >(); - typedef typename SimpleAssociativeContainer::key_type key_type; - typedef typename SimpleAssociativeContainer::value_type value_type; - typedef typename require_same::type req; - } + SimpleAssociativeContainerConcept() + { + typedef typename SimpleAssociativeContainer::key_type key_type; + typedef typename SimpleAssociativeContainer::value_type value_type; + BOOST_MPL_ASSERT((boost::is_same)); + } }; template struct PairAssociativeContainerConcept + : AssociativeContainerConcept { - void constraints() { - function_requires< AssociativeContainerConcept >(); - typedef typename SimpleAssociativeContainer::key_type key_type; - typedef typename SimpleAssociativeContainer::value_type value_type; - typedef typename SimpleAssociativeContainer::mapped_type mapped_type; - typedef std::pair required_value_type; - typedef typename require_same::type req; - } + PairAssociativeContainerConcept() + { + typedef typename SimpleAssociativeContainer::key_type key_type; + typedef typename SimpleAssociativeContainer::value_type value_type; + typedef typename SimpleAssociativeContainer::mapped_type mapped_type; + typedef std::pair required_value_type; + BOOST_MPL_ASSERT((boost::is_same)); + } }; template struct SortedAssociativeContainerConcept + : AssociativeContainerConcept + , ReversibleContainerConcept { - void constraints() { - function_requires< AssociativeContainerConcept >(); - function_requires< ReversibleContainerConcept >(); + SortedAssociativeContainerConcept() + { + SortedAssociativeContainer + c(kc), + c2(first, last), + c3(first, last, kc); - SortedAssociativeContainer - c(kc), - c2(first, last), - c3(first, last, kc); - - p = c.upper_bound(k); - p = c.lower_bound(k); - r = c.equal_range(k); + p = c.upper_bound(k); + p = c.lower_bound(k); + r = c.equal_range(k); - c.insert(p, t); + c.insert(p, t); - ignore_unused_variable_warning(c); - ignore_unused_variable_warning(c2); - ignore_unused_variable_warning(c3); - } - void const_constraints(const SortedAssociativeContainer& c) { - kc = c.key_comp(); - vc = c.value_comp(); + ignore_unused_variable_warning(c); + ignore_unused_variable_warning(c2); + ignore_unused_variable_warning(c3); + const_constraints(c); + } + + void const_constraints(const SortedAssociativeContainer& c) + { + kc = c.key_comp(); + vc = c.value_comp(); - cp = c.upper_bound(k); - cp = c.lower_bound(k); - cr = c.equal_range(k); - } - typename SortedAssociativeContainer::key_compare kc; - typename SortedAssociativeContainer::value_compare vc; - typename SortedAssociativeContainer::value_type t; - typename SortedAssociativeContainer::key_type k; - typedef typename SortedAssociativeContainer::iterator iterator; - typedef typename SortedAssociativeContainer::const_iterator const_iterator; - iterator p; - const_iterator cp; - std::pair r; - std::pair cr; - typename SortedAssociativeContainer::value_type* first, *last; + cp = c.upper_bound(k); + cp = c.lower_bound(k); + cr = c.equal_range(k); + } + + private: + static typename SortedAssociativeContainer::key_compare kc; + static typename SortedAssociativeContainer::value_compare vc; + static typename SortedAssociativeContainer::value_type t; + static typename SortedAssociativeContainer::key_type k; + typedef typename SortedAssociativeContainer::iterator iterator; + typedef typename SortedAssociativeContainer::const_iterator const_iterator; + + typedef SortedAssociativeContainerConcept self; + static iterator p; + static const_iterator cp; + static std::pair r; + static std::pair cr; + static typename SortedAssociativeContainer::value_type* first, *last; }; // HashedAssociativeContainer