From d4ecb93adbd4ad6923d266df9a6327b943d0a2e2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 24 Apr 2006 04:10:22 +0000 Subject: [PATCH 01/25] Rework concept checking to look lots more like ConceptGCC. [SVN r33775] --- include/boost/concept_check.hpp | 1209 ++++++++++++++++--------------- 1 file changed, 626 insertions(+), 583 deletions(-) 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 From 24326c9df51d4fcaa0027380b55304cad6173dae Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 29 Apr 2006 20:27:14 +0000 Subject: [PATCH 02/25] Fixes for concept checking; use destructors for checking classes, misc cleanup. [SVN r33862] --- Jamfile | 17 +- Jamfile.v2 | 16 +- class_concept_check_test.cpp | 16 +- class_concept_fail_expected.cpp | 13 +- concept_check_fail_expected.cpp | 10 +- function_requires_fail.cpp | 26 + include/boost/concept_check.hpp | 545 ++++++++---------- include/boost/concept_check/Attic/borland.hpp | 25 + include/boost/concept_check/Attic/general.hpp | 82 +++ .../concept_check/Attic/has_constraints.hpp | 31 + include/boost/concept_check/Attic/msvc.hpp | 62 ++ include/boost/concept_check/borland.hpp | 25 + include/boost/concept_check/general.hpp | 82 +++ .../boost/concept_check/has_constraints.hpp | 31 + include/boost/concept_check/msvc.hpp | 62 ++ old_concept_class_fail.cpp | 28 + old_concept_function_fail.cpp | 23 + old_concept_pass.cpp | 34 ++ old_concepts.hpp | 67 +++ 19 files changed, 864 insertions(+), 331 deletions(-) create mode 100755 function_requires_fail.cpp create mode 100755 include/boost/concept_check/Attic/borland.hpp create mode 100755 include/boost/concept_check/Attic/general.hpp create mode 100755 include/boost/concept_check/Attic/has_constraints.hpp create mode 100755 include/boost/concept_check/Attic/msvc.hpp create mode 100755 include/boost/concept_check/borland.hpp create mode 100755 include/boost/concept_check/general.hpp create mode 100755 include/boost/concept_check/has_constraints.hpp create mode 100755 include/boost/concept_check/msvc.hpp create mode 100755 old_concept_class_fail.cpp create mode 100755 old_concept_function_fail.cpp create mode 100755 old_concept_pass.cpp create mode 100755 old_concepts.hpp diff --git a/Jamfile b/Jamfile index 7cd68ec..782ed1a 100644 --- a/Jamfile +++ b/Jamfile @@ -3,9 +3,16 @@ subproject libs/concept_check ; import testing ; test-suite concept_check - : [ compile stl_concept_covering.cpp ] - [ compile concept_check_test.cpp ] - [ compile class_concept_check_test.cpp ] - [ link-fail concept_check_fail_expected.cpp ] - [ link-fail class_concept_fail_expected.cpp ] + : [ run stl_concept_covering.cpp ] + [ run concept_check_test.cpp ] + [ run class_concept_check_test.cpp ] + [ compile-fail concept_check_fail_expected.cpp ] + [ compile-fail class_concept_fail_expected.cpp ] + + # Backward compatibility tests + [ run old_concept_pass.cpp ] + [ compile-fail function_requires_fail.cpp ] + [ compile-fail old_concept_function_fail.cpp ] + [ compile-fail old_concept_class_fail.cpp ] ; + diff --git a/Jamfile.v2 b/Jamfile.v2 index 84bbb6d..a37786a 100644 --- a/Jamfile.v2 +++ b/Jamfile.v2 @@ -2,9 +2,15 @@ import testing ; test-suite concept_check - : [ compile stl_concept_covering.cpp ] - [ compile concept_check_test.cpp ] - [ compile class_concept_check_test.cpp ] - [ link-fail concept_check_fail_expected.cpp ] - [ link-fail class_concept_fail_expected.cpp ] + : [ run stl_concept_covering.cpp ] + [ run concept_check_test.cpp ] + [ run class_concept_check_test.cpp ] + [ compile-fail concept_check_fail_expected.cpp ] + [ compile-fail class_concept_fail_expected.cpp ] + + # Backward compatibility tests + [ run old_concept_pass.cpp ] + [ compile-fail function_requires_fail.cpp ] + [ compile-fail old_concept_function_fail.cpp ] + [ compile-fail old_concept_class_fail.cpp ] ; diff --git a/class_concept_check_test.cpp b/class_concept_check_test.cpp index e941682..d99845c 100644 --- a/class_concept_check_test.cpp +++ b/class_concept_check_test.cpp @@ -18,17 +18,17 @@ struct bar { bool operator()(int, char) { return true; } }; class class_requires_test { - BOOST_CLASS_REQUIRE(int, boost, EqualityComparableConcept); - typedef int* int_ptr; typedef const int* const_int_ptr; - BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, boost, EqualOpConcept); - BOOST_CLASS_REQUIRE3(foo, bool, int, boost, UnaryFunctionConcept); - BOOST_CLASS_REQUIRE4(bar, bool, int, char, boost, BinaryFunctionConcept); + BOOST_CONCEPT_ASSERT((boost::EqualityComparableConcept)); + typedef int* int_ptr; typedef const int* const_int_ptr; + BOOST_CONCEPT_ASSERT((boost::EqualOpConcept)); + BOOST_CONCEPT_ASSERT((boost::UnaryFunctionConcept)); +// BOOST_CONCEPT_ASSERT((boost::BinaryFunctionConcept)); }; int main() { - class_requires_test x; - boost::ignore_unused_variable_warning(x); - return 0; + class_requires_test x; + boost::ignore_unused_variable_warning(x); + return 0; } diff --git a/class_concept_fail_expected.cpp b/class_concept_fail_expected.cpp index 11f7f52..6cafbd4 100644 --- a/class_concept_fail_expected.cpp +++ b/class_concept_fail_expected.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Jeremy Siek 2000. +// (C) Copyright Jeremy Siek, David Abrahams 2000-2006. // 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) @@ -11,21 +11,22 @@ /* This file verifies that class_requires of the Boost Concept Checking - Library catches errors when it is suppose to. + Library catches errors when it is supposed to. */ struct foo { }; +template class class_requires_test { - BOOST_CLASS_REQUIRE(foo, boost, EqualityComparableConcept); + BOOST_CONCEPT_ASSERT((boost::EqualityComparableConcept)); }; int main() { - class_requires_test x; - (void)x; // suppress unused variable warning - return 0; + class_requires_test x; + (void)x; // suppress unused variable warning + return 0; } diff --git a/concept_check_fail_expected.cpp b/concept_check_fail_expected.cpp index 789bdf4..f213ab5 100644 --- a/concept_check_fail_expected.cpp +++ b/concept_check_fail_expected.cpp @@ -1,4 +1,4 @@ -// (C) Copyright Jeremy Siek 2000. +// (C) Copyright Jeremy Siek, David Abrahams 2000-2006. // 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) @@ -11,8 +11,8 @@ /* - This file verifies that function_requires() of the Boost Concept - Checking Library catches errors when it is suppose to. + This file verifies that BOOST_CONCEPT_ASSERT catches errors in + function context. */ @@ -21,6 +21,6 @@ struct foo { }; int main() { - boost::function_requires< boost::EqualityComparableConcept >(); - return 0; + BOOST_CONCEPT_ASSERT((boost::EqualityComparableConcept)); + return 0; } diff --git a/function_requires_fail.cpp b/function_requires_fail.cpp new file mode 100755 index 0000000..5c9a4f3 --- /dev/null +++ b/function_requires_fail.cpp @@ -0,0 +1,26 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + +#ifdef NDEBUG +# undef NDEBUG +#endif + +#include + +/* + + This file verifies that function_requires() of the Boost Concept + Checking Library catches errors when it is suppose to. + +*/ + +struct foo { }; + +int +main() +{ + boost::function_requires< boost::EqualityComparableConcept >(); + return 0; +} diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index eaa4ba0..c8aef71 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -20,6 +20,7 @@ # include # include # include +# include # include # include # include @@ -28,79 +29,28 @@ # include # include +// The old protocol used a constraints() member function in concept +// checking classes. If the compiler supports SFINAE, we can detect +// that function and seamlessly support the old concept checking +// classes. In this release, backward compatibility with the old +// concept checking classes is enabled by default, where available. +// The old protocol is deprecated, though, and backward compatibility +// will no longer be the default in the next release. +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_OLD_CONCEPT_SUPPORT) +# define BOOST_OLD_CONCEPT_SUPPORT +# endif + +# ifdef BOOST_MSVC +# include +# elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# include +# else +# include +# endif + namespace boost { -/* - "inline" is used for ignore_unused_variable_warning() - and function_requires() to make sure there is no - overhead with g++. - */ - -# 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 }; - }; - -# else - namespace concept_checking - { - template - struct test - { - static void inline failed() { new ((void*)0) T; } - }; - - template inline void instantiate(T const&) {} - } - - 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 \ - ] - // // Backward compatibility // @@ -108,14 +58,8 @@ namespace boost 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 } - template inline void ignore_unused_variable_warning(T const&) {} # define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ @@ -130,65 +74,59 @@ namespace boost # define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ BOOST_CONCEPT_ASSERT((ns::concept)) + + // + // Begin concept definitions + // template struct IntegerConcept { - IntegerConcept() { -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + ~IntegerConcept() { x.error_type_must_be_an_integer_type(); -#endif } private: - static T x; + T x; }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template <> struct IntegerConcept { IntegerConcept() {} }; - template <> struct IntegerConcept { IntegerConcept() {} }; - template <> struct IntegerConcept { IntegerConcept() {} }; - template <> struct IntegerConcept { IntegerConcept() {} }; - template <> struct IntegerConcept { IntegerConcept() {} }; - template <> struct IntegerConcept { IntegerConcept() {} }; + + 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 { - SignedIntegerConcept() { -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + ~SignedIntegerConcept() { x.error_type_must_be_a_signed_integer_type(); -#endif } private: - static T x; + T x; }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template <> struct SignedIntegerConcept { SignedIntegerConcept() {} }; - template <> struct SignedIntegerConcept { SignedIntegerConcept() {} }; - template <> struct SignedIntegerConcept { SignedIntegerConcept() {} }; + 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> { SignedIntegerConcept() {} }; -# endif + template <> struct SignedIntegerConcept< ::boost::long_long_type> { ~SignedIntegerConcept() {} }; // etc. #endif template struct UnsignedIntegerConcept { - UnsignedIntegerConcept() { -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + ~UnsignedIntegerConcept() { x.error_type_must_be_an_unsigned_integer_type(); -#endif } private: - static T x; + T x; }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template <> struct UnsignedIntegerConcept - { UnsignedIntegerConcept() {} }; + { ~UnsignedIntegerConcept() {} }; template <> struct UnsignedIntegerConcept - { UnsignedIntegerConcept() {} }; + { ~UnsignedIntegerConcept() {} }; template <> struct UnsignedIntegerConcept - { UnsignedIntegerConcept() {} }; + { ~UnsignedIntegerConcept() {} }; // etc. -#endif //=========================================================================== // Basic Concepts @@ -196,7 +134,7 @@ namespace boost template struct DefaultConstructibleConcept { - DefaultConstructibleConcept() { + ~DefaultConstructibleConcept() { TT a; // require default constructor ignore_unused_variable_warning(a); } @@ -205,7 +143,7 @@ namespace boost template struct AssignableConcept { - AssignableConcept() { + ~AssignableConcept() { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator #endif @@ -218,13 +156,13 @@ namespace boost #endif } private: - static TT a; + TT a; }; template struct CopyConstructibleConcept { - CopyConstructibleConcept() { + ~CopyConstructibleConcept() { TT a(b); // require copy constructor TT* ptr = &a; // require address of operator const_constraints(a); @@ -237,14 +175,14 @@ namespace boost ignore_unused_variable_warning(c); ignore_unused_variable_warning(ptr); } - static TT b; + TT b; }; // The SGI STL version of Assignable requires copy constructor and operator= template struct SGIAssignableConcept { - SGIAssignableConcept() { + ~SGIAssignableConcept() { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator @@ -260,18 +198,18 @@ namespace boost #endif ignore_unused_variable_warning(c); } - static TT a; + TT a; }; template struct ConvertibleConcept { - ConvertibleConcept() { + ~ConvertibleConcept() { Y y = x; ignore_unused_variable_warning(y); } private: - static X x; + X x; }; // The C++ standard requirements for many concepts talk about return @@ -292,60 +230,60 @@ namespace boost template struct EqualityComparableConcept { - EqualityComparableConcept() { + ~EqualityComparableConcept() { require_boolean_expr(a == b); require_boolean_expr(a != b); } private: - static TT a, b; + TT a, b; }; template struct LessThanComparableConcept { - LessThanComparableConcept() { + ~LessThanComparableConcept() { require_boolean_expr(a < b); } private: - static TT a, b; + TT a, b; }; // This is equivalent to SGI STL's LessThanComparable. template struct ComparableConcept { - ComparableConcept() { + ~ComparableConcept() { require_boolean_expr(a < b); require_boolean_expr(a > b); require_boolean_expr(a <= b); require_boolean_expr(a >= b); } private: - static TT a, b; + TT a, b; }; #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ template \ struct NAME { \ - NAME() { (void)constraints_(); } \ + ~NAME() { (void)constraints_(); } \ private: \ bool constraints_() { \ return a OP b; \ } \ - static First a; \ - static Second b; \ + First a; \ + Second b; \ } #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ template \ struct NAME { \ - NAME() { (void)constraints_(); } \ + ~NAME() { (void)constraints_(); } \ private: \ Ret constraints_() { \ return a OP b; \ } \ - static First a; \ - static Second b; \ + First a; \ + Second b; \ } BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept); @@ -367,99 +305,91 @@ namespace boost template struct GeneratorConcept { - GeneratorConcept() { - const Return& r = f(); // require operator() member function - ignore_unused_variable_warning(r); - } + ~GeneratorConcept() { test(is_void()); } + private: - static Func f; + 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; }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct GeneratorConcept - { - GeneratorConcept() { - f(); // require operator() member function - } - private: - static Func f; - }; -#endif - template struct UnaryFunctionConcept { - UnaryFunctionConcept() { - r = f(arg); // require operator() - } + ~UnaryFunctionConcept() { test(is_void()); } + private: - static Func f; - static Arg arg; - static Return r; + 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); + } + + Func f; + Arg arg; }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct UnaryFunctionConcept { - UnaryFunctionConcept() { - f(arg); // require operator() - } - private: - static Func f; - static Arg arg; - }; -#endif - template struct BinaryFunctionConcept { - BinaryFunctionConcept() { - r = f(first, second); // require operator() - } + ~BinaryFunctionConcept() { test(is_void()); } private: - static Func f; - static First first; - static Second second; - static Return r; + 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); + } + + Func f; + First first; + Second second; + Return r; }; -#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template - struct BinaryFunctionConcept - { - BinaryFunctionConcept() { - f(first, second); // require operator() - } - private: - static Func f; - static First first; - static Second second; - }; -#endif - template struct UnaryPredicateConcept { - UnaryPredicateConcept() { + ~UnaryPredicateConcept() { require_boolean_expr(f(arg)); // require operator() returning bool } private: - static Func f; - static Arg arg; + Func f; + Arg arg; }; template struct BinaryPredicateConcept { - BinaryPredicateConcept() { + ~BinaryPredicateConcept() { require_boolean_expr(f(a, b)); // require operator() returning bool } private: - static Func f; - static First a; - static Second b; + Func f; + First a; + Second b; }; // use this when functor is used inside a container class like std::set @@ -467,7 +397,7 @@ namespace boost struct Const_BinaryPredicateConcept : BinaryPredicateConcept { - Const_BinaryPredicateConcept() { + ~Const_BinaryPredicateConcept() { const_constraints(f); } private: @@ -475,9 +405,9 @@ namespace boost // operator() must be a const member function require_boolean_expr(fun(a, b)); } - static Func f; - static First a; - static Second b; + Func f; + First a; + Second b; }; template @@ -486,7 +416,7 @@ namespace boost { typedef typename Func::result_type result_type; - AdaptableGeneratorConcept() + ~AdaptableGeneratorConcept() { BOOST_MPL_ASSERT((is_convertible)); } @@ -499,7 +429,7 @@ namespace boost typedef typename Func::argument_type argument_type; typedef typename Func::result_type result_type; - AdaptableUnaryFunctionConcept() + ~AdaptableUnaryFunctionConcept() { BOOST_MPL_ASSERT((is_convertible)); BOOST_MPL_ASSERT((is_convertible)); @@ -519,7 +449,7 @@ namespace boost typedef typename Func::second_argument_type second_argument_type; typedef typename Func::result_type result_type; - AdaptableBinaryFunctionConcept() + ~AdaptableBinaryFunctionConcept() { BOOST_MPL_ASSERT((is_convertible)); BOOST_MPL_ASSERT((is_convertible)); @@ -554,10 +484,10 @@ namespace boost typedef typename boost::detail::iterator_traits::pointer pointer; typedef typename boost::detail::iterator_traits::iterator_category iterator_category; - InputIteratorConcept() + ~InputIteratorConcept() { - SignedIntegerConcept(); - ConvertibleConcept(); + BOOST_CONCEPT_ASSERT((SignedIntegerConcept)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept)); TT j(i); (void)*i; // require dereference operator @@ -565,70 +495,70 @@ namespace boost i++; // require postincrement operator } private: - static TT i; + TT i; }; template struct OutputIteratorConcept : AssignableConcept { - OutputIteratorConcept() { + ~OutputIteratorConcept() { ++i; // require preincrement operator i++; // require postincrement operator *i++ = t; // require postincrement and assignment } private: - static TT i, j; - static ValueT t; + TT i, j; + ValueT t; }; template struct ForwardIteratorConcept : InputIteratorConcept { - ForwardIteratorConcept() + ~ForwardIteratorConcept() { - ConvertibleConcept< + BOOST_CONCEPT_ASSERT((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; + TT i; }; template struct Mutable_ForwardIteratorConcept : ForwardIteratorConcept { - Mutable_ForwardIteratorConcept() { + ~Mutable_ForwardIteratorConcept() { *i++ = *i; // require postincrement and assignment } private: - static TT i; + TT i; }; template struct BidirectionalIteratorConcept : ForwardIteratorConcept { - BidirectionalIteratorConcept() + ~BidirectionalIteratorConcept() { - ConvertibleConcept< + BOOST_CONCEPT_ASSERT((ConvertibleConcept< BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::iterator_category , std::bidirectional_iterator_tag - >(); + >)); --i; // require predecrement operator i--; // require postdecrement operator } private: - static TT i; + TT i; }; template @@ -636,12 +566,12 @@ namespace boost : BidirectionalIteratorConcept , Mutable_ForwardIteratorConcept { - Mutable_BidirectionalIteratorConcept() + ~Mutable_BidirectionalIteratorConcept() { *i-- = *i; // require postdecrement and assignment } private: - static TT i; + TT i; }; @@ -650,12 +580,12 @@ namespace boost : BidirectionalIteratorConcept , ComparableConcept { - RandomAccessIteratorConcept() + ~RandomAccessIteratorConcept() { - ConvertibleConcept< + BOOST_CONCEPT_ASSERT((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 @@ -666,8 +596,8 @@ namespace boost } private: - static TT a, b; - static TT i, j; + TT a, b; + TT i, j; typename boost::detail::iterator_traits::difference_type n; }; @@ -676,11 +606,11 @@ namespace boost : RandomAccessIteratorConcept , Mutable_BidirectionalIteratorConcept { - Mutable_RandomAccessIteratorConcept() { + ~Mutable_RandomAccessIteratorConcept() { i[n] = *i; // require element access and assignment } private: - static TT i; + TT i; typename boost::detail::iterator_traits::difference_type n; }; @@ -698,9 +628,9 @@ namespace boost typedef typename Container::const_pointer const_pointer; typedef typename Container::const_iterator const_iterator; - ContainerConcept() + ~ContainerConcept() { - InputIteratorConcept(); + BOOST_CONCEPT_ASSERT((InputIteratorConcept)); const_constraints(c); } @@ -712,10 +642,10 @@ namespace boost n = cc.max_size(); b = cc.empty(); } - static Container c; - static bool b; - static const_iterator i; - static size_type n; + Container c; + bool b; + const_iterator i; + size_type n; }; template @@ -726,10 +656,12 @@ namespace boost typedef typename Container::iterator iterator; typedef typename Container::pointer pointer; - Mutable_ContainerConcept() + ~Mutable_ContainerConcept() { - AssignableConcept(); - InputIteratorConcept(); + BOOST_CONCEPT_ASSERT(( + AssignableConcept)); + + BOOST_CONCEPT_ASSERT((InputIteratorConcept)); i = c.begin(); i = c.end(); @@ -737,17 +669,20 @@ namespace boost } private: - static iterator i; - static Container c, c2; + iterator i; + Container c, c2; }; template struct ForwardContainerConcept : ContainerConcept { - ForwardContainerConcept() + ~ForwardContainerConcept() { - ForwardIteratorConcept(); + BOOST_CONCEPT_ASSERT(( + ForwardIteratorConcept< + typename ForwardContainerConcept::const_iterator + >)); } }; @@ -756,11 +691,12 @@ namespace boost : ForwardContainerConcept , Mutable_ContainerConcept { - Mutable_ForwardContainerConcept() + ~Mutable_ForwardContainerConcept() { - Mutable_ForwardIteratorConcept< - typename Mutable_ForwardContainerConcept::iterator - >(); + BOOST_CONCEPT_ASSERT(( + Mutable_ForwardIteratorConcept< + typename Mutable_ForwardContainerConcept::iterator + >)); } }; @@ -772,10 +708,14 @@ namespace boost ReversibleContainer::const_reverse_iterator const_reverse_iterator; - ReversibleContainerConcept() + ~ReversibleContainerConcept() { - BidirectionalIteratorConcept(); - BidirectionalIteratorConcept(); + BOOST_CONCEPT_ASSERT(( + BidirectionalIteratorConcept< + typename ReversibleContainerConcept::const_iterator>)); + + BOOST_CONCEPT_ASSERT((BidirectionalIteratorConcept)); + const_constraints(c); } private: @@ -784,7 +724,7 @@ namespace boost const_reverse_iterator i = cc.rbegin(); i = cc.rend(); } - static ReversibleContainer c; + ReversibleContainer c; }; template @@ -795,15 +735,15 @@ namespace boost typedef typename ReversibleContainer::iterator iterator; typedef typename ReversibleContainer::reverse_iterator reverse_iterator; - Mutable_ReversibleContainerConcept() + ~Mutable_ReversibleContainerConcept() { - Mutable_BidirectionalIteratorConcept(); - Mutable_BidirectionalIteratorConcept(); + BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIteratorConcept)); + BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIteratorConcept)); reverse_iterator i = c.rbegin(); i = c.rend(); } private: - static ReversibleContainer c; + ReversibleContainer c; }; template @@ -813,11 +753,12 @@ namespace boost typedef typename RandomAccessContainer::size_type size_type; typedef typename RandomAccessContainer::const_reference const_reference; - RandomAccessContainerConcept() + ~RandomAccessContainerConcept() { - RandomAccessIteratorConcept< - typename RandomAccessContainerConcept::const_iterator - >(); + BOOST_CONCEPT_ASSERT(( + RandomAccessIteratorConcept< + typename RandomAccessContainerConcept::const_iterator + >)); const_constraints(c); } @@ -828,8 +769,8 @@ namespace boost ignore_unused_variable_warning(r); } - static RandomAccessContainer c; - static size_type n; + RandomAccessContainer c; + size_type n; }; template @@ -840,18 +781,18 @@ namespace boost private: typedef Mutable_RandomAccessContainerConcept self; public: - Mutable_RandomAccessContainerConcept() + ~Mutable_RandomAccessContainerConcept() { - Mutable_RandomAccessIteratorConcept(); - Mutable_RandomAccessIteratorConcept(); + BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIteratorConcept)); + BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIteratorConcept)); typename self::reference r = c[i]; ignore_unused_variable_warning(r); } private: - static typename Mutable_ReversibleContainerConcept::size_type i; - static RandomAccessContainer c; + typename Mutable_ReversibleContainerConcept::size_type i; + RandomAccessContainer c; }; // A Sequence is inherently mutable @@ -863,7 +804,7 @@ namespace boost // ... so why aren't we following the standard? --DWA , DefaultConstructibleConcept { - SequenceConcept() + ~SequenceConcept() { Sequence c(n), @@ -891,31 +832,31 @@ namespace boost 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; + typename Sequence::value_type t; + typename Sequence::size_type n; + typename Sequence::value_type* first, *last; + typename Sequence::iterator p, q; }; template struct FrontInsertionSequenceConcept : SequenceConcept { - FrontInsertionSequenceConcept() + ~FrontInsertionSequenceConcept() { c.push_front(t); c.pop_front(); } private: - static FrontInsertionSequence c; - static typename FrontInsertionSequence::value_type t; + FrontInsertionSequence c; + typename FrontInsertionSequence::value_type t; }; template struct BackInsertionSequenceConcept : SequenceConcept { - BackInsertionSequenceConcept() + ~BackInsertionSequenceConcept() { c.push_back(t); c.pop_back(); @@ -929,8 +870,8 @@ namespace boost r = cc.back(); ignore_unused_variable_warning(r); }; - static BackInsertionSequence c; - static typename BackInsertionSequence::value_type t; + BackInsertionSequence c; + typename BackInsertionSequence::value_type t; }; template @@ -943,7 +884,7 @@ namespace boost typedef typename AssociativeContainer::value_compare value_compare; typedef typename AssociativeContainer::iterator iterator; - AssociativeContainerConcept() + ~AssociativeContainerConcept() { i = c.find(k); r = c.equal_range(k); @@ -951,10 +892,10 @@ namespace boost c.erase(i); c.erase(r.first, r.second); const_constraints(c); - BinaryPredicateConcept(); + BOOST_CONCEPT_ASSERT((BinaryPredicateConcept)); - typedef typename AssociativeContainerConcept::value_type value_type; - BinaryPredicateConcept(); + typedef typename AssociativeContainerConcept::value_type value_type_; + BOOST_CONCEPT_ASSERT((BinaryPredicateConcept)); } // Redundant with the base concept, but it helps below. @@ -967,20 +908,20 @@ namespace boost 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; + AssociativeContainer c; + iterator i; + std::pair r; + const_iterator ci; + std::pair cr; + typename AssociativeContainer::key_type k; + typename AssociativeContainer::size_type n; }; template struct UniqueAssociativeContainerConcept : AssociativeContainerConcept { - UniqueAssociativeContainerConcept() + ~UniqueAssociativeContainerConcept() { UniqueAssociativeContainer c(first, last); @@ -990,16 +931,16 @@ namespace boost ignore_unused_variable_warning(c); } private: - static std::pair pos_flag; - static typename UniqueAssociativeContainer::value_type t; - static typename UniqueAssociativeContainer::value_type* first, *last; + std::pair pos_flag; + typename UniqueAssociativeContainer::value_type t; + typename UniqueAssociativeContainer::value_type* first, *last; }; template struct MultipleAssociativeContainerConcept : AssociativeContainerConcept { - MultipleAssociativeContainerConcept() + ~MultipleAssociativeContainerConcept() { MultipleAssociativeContainer c(first, last); @@ -1010,16 +951,16 @@ namespace boost ignore_unused_variable_warning(pos); } private: - static typename MultipleAssociativeContainer::iterator pos; - static typename MultipleAssociativeContainer::value_type t; - static typename MultipleAssociativeContainer::value_type* first, *last; + typename MultipleAssociativeContainer::iterator pos; + typename MultipleAssociativeContainer::value_type t; + typename MultipleAssociativeContainer::value_type* first, *last; }; template struct SimpleAssociativeContainerConcept : AssociativeContainerConcept { - SimpleAssociativeContainerConcept() + ~SimpleAssociativeContainerConcept() { typedef typename SimpleAssociativeContainer::key_type key_type; typedef typename SimpleAssociativeContainer::value_type value_type; @@ -1031,7 +972,7 @@ namespace boost struct PairAssociativeContainerConcept : AssociativeContainerConcept { - PairAssociativeContainerConcept() + ~PairAssociativeContainerConcept() { typedef typename SimpleAssociativeContainer::key_type key_type; typedef typename SimpleAssociativeContainer::value_type value_type; @@ -1046,7 +987,7 @@ namespace boost : AssociativeContainerConcept , ReversibleContainerConcept { - SortedAssociativeContainerConcept() + ~SortedAssociativeContainerConcept() { SortedAssociativeContainer c(kc), @@ -1076,19 +1017,19 @@ namespace boost } 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; + 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; 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; + iterator p; + const_iterator cp; + std::pair r; + std::pair cr; + typename SortedAssociativeContainer::value_type* first, *last; }; // HashedAssociativeContainer diff --git a/include/boost/concept_check/Attic/borland.hpp b/include/boost/concept_check/Attic/borland.hpp new file mode 100755 index 0000000..107926b --- /dev/null +++ b/include/boost/concept_check/Attic/borland.hpp @@ -0,0 +1,25 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP + +namespace boost { + +template +struct concept_check; + +template +struct concept_check +{ + enum { instantiate = sizeof((((Model*)0)->~Model()), 3) }; +}; + +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + boost::concept_check::instantiate \ + } + +} // namespace boost::concept_checking + +#endif // BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP diff --git a/include/boost/concept_check/Attic/general.hpp b/include/boost/concept_check/Attic/general.hpp new file mode 100755 index 0000000..cd09fb0 --- /dev/null +++ b/include/boost/concept_check/Attic/general.hpp @@ -0,0 +1,82 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +// This implementation works on GCC and Comeau, but has actually been +// fairly carefully tuned to work on GCC versions starting with +// gcc-2.95.x. If you're trying to get an additional compiler to pass +// the tests you might consider breaking out a separate gcc.hpp and +// starting over on the general case. +namespace boost +{ + namespace concept_checking + { + template struct instantiate {}; + } + + template struct concept_check_; + + template + void concept_check_failed() + { + ((Model*)0)->~Model(); + } + + template + struct concept_check + { + concept_checking::instantiate > x; + enum { instantiate = 1 }; + }; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + + template + void constraint_check_failed() + { + ((Model*)0)->constraints(); + } + + template + struct constraint_check + { + concept_checking::instantiate > x; + enum { instantiate = 1 }; + }; + + template + struct concept_check_ + : mpl::if_c< + concept_checking::has_constraints::value + , constraint_check + , concept_check + >::type + {}; + +# else + + template + struct concept_check_ + : concept_check + {}; + +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + ::boost::concept_check_::instantiate \ + } +} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/include/boost/concept_check/Attic/has_constraints.hpp b/include/boost/concept_check/Attic/has_constraints.hpp new file mode 100755 index 0000000..e19f664 --- /dev/null +++ b/include/boost/concept_check/Attic/has_constraints.hpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP + +namespace boost { namespace concept_checking { + +// Here we implement the "metafunction" that detects whether a +// constraints metafunction exists +typedef char yes; +typedef char (&no)[2]; + +template +struct wrap_constraints {}; + +template +inline yes has_constraints_(Model*, wrap_constraints* = 0); +inline no has_constraints_(...); + +template +struct has_constraints +{ + BOOST_STATIC_CONSTANT( + bool + , value = sizeof( concept_checking::has_constraints_((Model*)0) ) == 1 ); +}; + +}} // namespace boost::concept_checking + +#endif // BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP diff --git a/include/boost/concept_check/Attic/msvc.hpp b/include/boost/concept_check/Attic/msvc.hpp new file mode 100755 index 0000000..102cc07 --- /dev/null +++ b/include/boost/concept_check/Attic/msvc.hpp @@ -0,0 +1,62 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +namespace boost +{ + template + struct concept_check + { + virtual void failed(Model* x) + { + x->~Model(); + } + + int test; + }; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + + template + struct constraint_check + { + virtual void failed(Model* x) + { + x->constraints(); + } + + int test; + }; + + template + typename mpl::if_c< + concept_checking::has_constraints::value + , constraint_check + , concept_check + >::type concept_check_(void(*)(Model)); + +# else + + template + concept_check concept_check_(void(*)(Model)); + +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(boost::concept_check_((void(*) ModelInParens)0).test) \ + } +} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/include/boost/concept_check/borland.hpp b/include/boost/concept_check/borland.hpp new file mode 100755 index 0000000..107926b --- /dev/null +++ b/include/boost/concept_check/borland.hpp @@ -0,0 +1,25 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP + +namespace boost { + +template +struct concept_check; + +template +struct concept_check +{ + enum { instantiate = sizeof((((Model*)0)->~Model()), 3) }; +}; + +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + boost::concept_check::instantiate \ + } + +} // namespace boost::concept_checking + +#endif // BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP diff --git a/include/boost/concept_check/general.hpp b/include/boost/concept_check/general.hpp new file mode 100755 index 0000000..cd09fb0 --- /dev/null +++ b/include/boost/concept_check/general.hpp @@ -0,0 +1,82 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +// This implementation works on GCC and Comeau, but has actually been +// fairly carefully tuned to work on GCC versions starting with +// gcc-2.95.x. If you're trying to get an additional compiler to pass +// the tests you might consider breaking out a separate gcc.hpp and +// starting over on the general case. +namespace boost +{ + namespace concept_checking + { + template struct instantiate {}; + } + + template struct concept_check_; + + template + void concept_check_failed() + { + ((Model*)0)->~Model(); + } + + template + struct concept_check + { + concept_checking::instantiate > x; + enum { instantiate = 1 }; + }; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + + template + void constraint_check_failed() + { + ((Model*)0)->constraints(); + } + + template + struct constraint_check + { + concept_checking::instantiate > x; + enum { instantiate = 1 }; + }; + + template + struct concept_check_ + : mpl::if_c< + concept_checking::has_constraints::value + , constraint_check + , concept_check + >::type + {}; + +# else + + template + struct concept_check_ + : concept_check + {}; + +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + ::boost::concept_check_::instantiate \ + } +} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/include/boost/concept_check/has_constraints.hpp b/include/boost/concept_check/has_constraints.hpp new file mode 100755 index 0000000..e19f664 --- /dev/null +++ b/include/boost/concept_check/has_constraints.hpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP + +namespace boost { namespace concept_checking { + +// Here we implement the "metafunction" that detects whether a +// constraints metafunction exists +typedef char yes; +typedef char (&no)[2]; + +template +struct wrap_constraints {}; + +template +inline yes has_constraints_(Model*, wrap_constraints* = 0); +inline no has_constraints_(...); + +template +struct has_constraints +{ + BOOST_STATIC_CONSTANT( + bool + , value = sizeof( concept_checking::has_constraints_((Model*)0) ) == 1 ); +}; + +}} // namespace boost::concept_checking + +#endif // BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP diff --git a/include/boost/concept_check/msvc.hpp b/include/boost/concept_check/msvc.hpp new file mode 100755 index 0000000..102cc07 --- /dev/null +++ b/include/boost/concept_check/msvc.hpp @@ -0,0 +1,62 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +namespace boost +{ + template + struct concept_check + { + virtual void failed(Model* x) + { + x->~Model(); + } + + int test; + }; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + + template + struct constraint_check + { + virtual void failed(Model* x) + { + x->constraints(); + } + + int test; + }; + + template + typename mpl::if_c< + concept_checking::has_constraints::value + , constraint_check + , concept_check + >::type concept_check_(void(*)(Model)); + +# else + + template + concept_check concept_check_(void(*)(Model)); + +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(boost::concept_check_((void(*) ModelInParens)0).test) \ + } +} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/old_concept_class_fail.cpp b/old_concept_class_fail.cpp new file mode 100755 index 0000000..be41037 --- /dev/null +++ b/old_concept_class_fail.cpp @@ -0,0 +1,28 @@ +// (C) Copyright Jeremy Siek, David Abrahams 2000-2006. +// 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) +// +// Change Log: +// 20 Jan 2001 - Added warning suppression (David Abrahams) + +#include "old_concepts.hpp" + +// This file verifies that concepts written the old way still catch +// errors in class context. This is not expected to work on compilers +// without SFINAE support. + +struct foo { }; + +class class_requires_test +{ + BOOST_CLASS_REQUIRE(foo, old, EqualityComparableConcept); +}; + +int +main() +{ + class_requires_test x; + (void)x; // suppress unused variable warning + return 0; +} diff --git a/old_concept_function_fail.cpp b/old_concept_function_fail.cpp new file mode 100755 index 0000000..6b7bf30 --- /dev/null +++ b/old_concept_function_fail.cpp @@ -0,0 +1,23 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + +#ifdef NDEBUG +# undef NDEBUG +#endif + +#include "old_concepts.hpp" + +// This file verifies that concepts written the old way still catch +// errors in function context. This is not expected to work on +// compilers without SFINAE support. + +struct foo { }; + +int +main() +{ + boost::function_requires< old::EqualityComparableConcept >(); + return 0; +} diff --git a/old_concept_pass.cpp b/old_concept_pass.cpp new file mode 100755 index 0000000..e9601fc --- /dev/null +++ b/old_concept_pass.cpp @@ -0,0 +1,34 @@ +// (C) Copyright Jeremy Siek, David Abrahams 2000-2006. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include "old_concepts.hpp" + +// This test verifies that use of the old-style concept checking +// classes still compiles (but not that it detects constraint +// violations). We check them with the old-style macros just for +// completeness, since those macros stranslate into +// BOOST_CONCEPT_ASSERTs. + +struct foo { bool operator()(int) { return true; } }; +struct bar { bool operator()(int, char) { return true; } }; + + +class class_requires_test +{ + BOOST_CLASS_REQUIRE(int, old, EqualityComparableConcept); + typedef int* int_ptr; typedef const int* const_int_ptr; + BOOST_CLASS_REQUIRE2(int_ptr, const_int_ptr, old, EqualOpConcept); + BOOST_CLASS_REQUIRE3(foo, bool, int, old, UnaryFunctionConcept); + BOOST_CLASS_REQUIRE4(bar, bool, int, char, old, BinaryFunctionConcept); +}; + +int +main() +{ + class_requires_test x; + boost::ignore_unused_variable_warning(x); + return 0; +} diff --git a/old_concepts.hpp b/old_concepts.hpp new file mode 100755 index 0000000..76fad3c --- /dev/null +++ b/old_concepts.hpp @@ -0,0 +1,67 @@ +// Copyright Jeremy Siek, David Abrahams 2000-2006. 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) +#ifndef BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP +# define BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP + +#include + +namespace old +{ + template + void require_boolean_expr(const TT& t) { + bool x = t; + boost::ignore_unused_variable_warning(x); + } + + template + struct EqualityComparableConcept + { + void constraints() { + boost::require_boolean_expr(a == b); + boost::require_boolean_expr(a != b); + } + TT a, b; + }; + + template + struct UnaryFunctionConcept + { + // required in case any of our template args are const-qualified: + UnaryFunctionConcept(); + + void constraints() { + r = f(arg); // require operator() + } + Func f; + Arg arg; + Return r; + }; + + template + struct BinaryFunctionConcept + { + void constraints() { + r = f(first, second); // require operator() + } + Func f; + First first; + Second second; + Return r; + }; + +#define 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_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept); +} + +#endif // BOOST_LIBS_CONCEPT_CHECK_OLD_CONCEPTS_DWA2006428_HPP From 3c2a976d2a0e62aefece9ba137ed766c2d7b3a1b Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 30 Apr 2006 03:01:58 +0000 Subject: [PATCH 03/25] Workarounds for a nasty vc-7.1 bug that only shows up in the iterator library tests. [SVN r33866] --- include/boost/concept_check/Attic/msvc.hpp | 92 ++++++++++++++-------- include/boost/concept_check/msvc.hpp | 92 ++++++++++++++-------- 2 files changed, 120 insertions(+), 64 deletions(-) diff --git a/include/boost/concept_check/Attic/msvc.hpp b/include/boost/concept_check/Attic/msvc.hpp index 102cc07..3968469 100755 --- a/include/boost/concept_check/Attic/msvc.hpp +++ b/include/boost/concept_check/Attic/msvc.hpp @@ -11,52 +11,80 @@ namespace boost -{ - template - struct concept_check +{ + namespace concept_checking { - virtual void failed(Model* x) - { - x->~Model(); - } - - int test; - }; - + template + struct concept_check_ + { + virtual void failed(Model* x) + { + x->~Model(); + } + }; + } + # ifdef BOOST_OLD_CONCEPT_SUPPORT - template - struct constraint_check + namespace concept_checking { - virtual void failed(Model* x) - { - x->constraints(); - } + template + struct constraint_check + { + virtual void failed(Model* x) + { + x->constraints(); + } + }; + } + + template + struct concept_check + : mpl::if_c< + concept_checking::has_constraints::value + , concept_checking::constraint_check + , concept_checking::concept_check_ + >::type + {}; - int test; - }; +# else template - typename mpl::if_c< - concept_checking::has_constraints::value - , constraint_check - , concept_check - >::type concept_check_(void(*)(Model)); + struct concept_check + : concept_checking::concept_check_ + {}; + +# endif + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1310) + + // + // The iterator library sees some really strange errors unless we + // use partial specialization to extract the model type with + // msvc-7.1 + // + template + struct concept_check + : concept_check + { }; + +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept_check) \ + } # else template - concept_check concept_check_(void(*)(Model)); + concept_check + concept_check_(void(*)(Model)); -# endif - - // Usage, in class or function context: - // - // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); -# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - sizeof(boost::concept_check_((void(*) ModelInParens)0).test) \ + sizeof(::boost::concept_check_((void(*) ModelInParens)0)) \ } + +# endif } #endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/include/boost/concept_check/msvc.hpp b/include/boost/concept_check/msvc.hpp index 102cc07..3968469 100755 --- a/include/boost/concept_check/msvc.hpp +++ b/include/boost/concept_check/msvc.hpp @@ -11,52 +11,80 @@ namespace boost -{ - template - struct concept_check +{ + namespace concept_checking { - virtual void failed(Model* x) - { - x->~Model(); - } - - int test; - }; - + template + struct concept_check_ + { + virtual void failed(Model* x) + { + x->~Model(); + } + }; + } + # ifdef BOOST_OLD_CONCEPT_SUPPORT - template - struct constraint_check + namespace concept_checking { - virtual void failed(Model* x) - { - x->constraints(); - } + template + struct constraint_check + { + virtual void failed(Model* x) + { + x->constraints(); + } + }; + } + + template + struct concept_check + : mpl::if_c< + concept_checking::has_constraints::value + , concept_checking::constraint_check + , concept_checking::concept_check_ + >::type + {}; - int test; - }; +# else template - typename mpl::if_c< - concept_checking::has_constraints::value - , constraint_check - , concept_check - >::type concept_check_(void(*)(Model)); + struct concept_check + : concept_checking::concept_check_ + {}; + +# endif + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1310) + + // + // The iterator library sees some really strange errors unless we + // use partial specialization to extract the model type with + // msvc-7.1 + // + template + struct concept_check + : concept_check + { }; + +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept_check) \ + } # else template - concept_check concept_check_(void(*)(Model)); + concept_check + concept_check_(void(*)(Model)); -# endif - - // Usage, in class or function context: - // - // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); -# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - sizeof(boost::concept_check_((void(*) ModelInParens)0).test) \ + sizeof(::boost::concept_check_((void(*) ModelInParens)0)) \ } + +# endif } #endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP From 3bce136d94c0e10a67ada008b3dde9f5cb546f4e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 30 Apr 2006 03:33:33 +0000 Subject: [PATCH 04/25] use idiomatic convertibility assertions. [SVN r33869] --- include/boost/concept_check.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index c8aef71..e4f06fb 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -418,7 +418,7 @@ namespace boost ~AdaptableGeneratorConcept() { - BOOST_MPL_ASSERT((is_convertible)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept)); } }; @@ -431,8 +431,8 @@ namespace boost ~AdaptableUnaryFunctionConcept() { - BOOST_MPL_ASSERT((is_convertible)); - BOOST_MPL_ASSERT((is_convertible)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept)); } }; @@ -451,9 +451,9 @@ namespace boost ~AdaptableBinaryFunctionConcept() { - BOOST_MPL_ASSERT((is_convertible)); - BOOST_MPL_ASSERT((is_convertible)); - BOOST_MPL_ASSERT((is_convertible)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept)); } }; From 80cbd761890c89fd285a76f85e7ba2863ddac8e2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 30 Apr 2006 20:54:13 +0000 Subject: [PATCH 05/25] Misc cleanups, missing extensions of integral types to (un)signed char and, where apropriate, the long long types. [SVN r33877] --- include/boost/concept_check.hpp | 40 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index e4f06fb..23780cf 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -87,12 +87,14 @@ namespace boost T x; }; - template <> struct IntegerConcept { ~IntegerConcept() {} }; - template <> struct IntegerConcept { ~IntegerConcept() {} }; - template <> struct IntegerConcept { ~IntegerConcept() {} }; - template <> struct IntegerConcept { ~IntegerConcept() {} }; - template <> struct IntegerConcept { ~IntegerConcept() {} }; - template <> struct IntegerConcept { ~IntegerConcept() {} }; + template <> struct IntegerConcept {}; + template <> struct IntegerConcept {}; + template <> struct IntegerConcept {}; + template <> struct IntegerConcept {}; + template <> struct IntegerConcept {}; + template <> struct IntegerConcept {}; + template <> struct IntegerConcept {}; + template <> struct IntegerConcept {}; // etc. template @@ -103,11 +105,12 @@ namespace boost private: T x; }; - template <> struct SignedIntegerConcept { ~SignedIntegerConcept() {} }; - template <> struct SignedIntegerConcept { ~SignedIntegerConcept() {} }; - template <> struct SignedIntegerConcept { ~SignedIntegerConcept() {} }; + template <> struct SignedIntegerConcept { }; + template <> struct SignedIntegerConcept {}; + template <> struct SignedIntegerConcept {}; + template <> struct SignedIntegerConcept {}; # if defined(BOOST_HAS_LONG_LONG) - template <> struct SignedIntegerConcept< ::boost::long_long_type> { ~SignedIntegerConcept() {} }; + template <> struct SignedIntegerConcept< ::boost::long_long_type> {}; // etc. #endif @@ -120,12 +123,15 @@ namespace boost T x; }; - template <> struct UnsignedIntegerConcept - { ~UnsignedIntegerConcept() {} }; - template <> struct UnsignedIntegerConcept - { ~UnsignedIntegerConcept() {} }; - template <> struct UnsignedIntegerConcept - { ~UnsignedIntegerConcept() {} }; + template <> struct UnsignedIntegerConcept {}; + template <> struct UnsignedIntegerConcept {}; + template <> struct UnsignedIntegerConcept {}; + template <> struct UnsignedIntegerConcept {}; +# if defined(BOOST_HAS_LONG_LONG) + template <> struct UnsignedIntegerConcept< ::boost::ulong_long_type> {}; + // etc. +#endif + // etc. //=========================================================================== @@ -428,7 +434,7 @@ namespace boost { typedef typename Func::argument_type argument_type; typedef typename Func::result_type result_type; - + ~AdaptableUnaryFunctionConcept() { BOOST_CONCEPT_ASSERT((ConvertibleConcept)); From bfb64284174df22f56e85dda5b001ecbc3d62bbf Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 1 May 2006 12:50:48 +0000 Subject: [PATCH 06/25] Factored out BOOST_CONCEPT_ASSERT into concept_check/assert.hpp Fixed the implementation for GCC 3.3.x and comeau Added BOOST_CONCEPT_WHERE, and tests [SVN r33887] --- Jamfile.v2 | 3 ++ fake_sort.hpp | 22 ++++++++ include/boost/concept_check.hpp | 25 +--------- include/boost/concept_check/Attic/borland.hpp | 12 +++-- include/boost/concept_check/Attic/general.hpp | 50 +++++++------------ include/boost/concept_check/Attic/msvc.hpp | 23 ++++++--- include/boost/concept_check/assert.hpp | 42 ++++++++++++++++ include/boost/concept_check/where.hpp | 50 +++++++++++++++++++ where.cpp | 13 +++++ where_fail.cpp | 13 +++++ 10 files changed, 186 insertions(+), 67 deletions(-) create mode 100755 fake_sort.hpp create mode 100755 include/boost/concept_check/assert.hpp create mode 100755 include/boost/concept_check/where.hpp create mode 100755 where.cpp create mode 100755 where_fail.cpp diff --git a/Jamfile.v2 b/Jamfile.v2 index a37786a..02efb76 100644 --- a/Jamfile.v2 +++ b/Jamfile.v2 @@ -8,6 +8,9 @@ test-suite concept_check [ compile-fail concept_check_fail_expected.cpp ] [ compile-fail class_concept_fail_expected.cpp ] + [ run where.cpp ] + [ compile-fail where_fail.cpp ] + # Backward compatibility tests [ run old_concept_pass.cpp ] [ compile-fail function_requires_fail.cpp ] diff --git a/fake_sort.hpp b/fake_sort.hpp new file mode 100755 index 0000000..e96504f --- /dev/null +++ b/fake_sort.hpp @@ -0,0 +1,22 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP +# define BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP + +# include +# include +# include + +template +BOOST_CONCEPT_WHERE( + ((boost::Mutable_RandomAccessIteratorConcept)) + ((boost::LessThanComparableConcept::value_type>)) + + , (void)) +fake_sort(RanIter,RanIter) +{ + +} + +#endif // BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 23780cf..37f435e 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -15,38 +15,17 @@ #ifndef BOOST_CONCEPT_CHECKS_HPP # define BOOST_CONCEPT_CHECKS_HPP -# include +# include + # include # include # include # include # include # include -# include # include -# include -# include -# include # include -// The old protocol used a constraints() member function in concept -// checking classes. If the compiler supports SFINAE, we can detect -// that function and seamlessly support the old concept checking -// classes. In this release, backward compatibility with the old -// concept checking classes is enabled by default, where available. -// The old protocol is deprecated, though, and backward compatibility -// will no longer be the default in the next release. -# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_OLD_CONCEPT_SUPPORT) -# define BOOST_OLD_CONCEPT_SUPPORT -# endif - -# ifdef BOOST_MSVC -# include -# elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# include -# else -# include -# endif namespace boost { diff --git a/include/boost/concept_check/Attic/borland.hpp b/include/boost/concept_check/Attic/borland.hpp index 107926b..f82c1c8 100755 --- a/include/boost/concept_check/Attic/borland.hpp +++ b/include/boost/concept_check/Attic/borland.hpp @@ -4,9 +4,11 @@ #ifndef BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP # define BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP +# include + namespace boost { -template +template struct concept_check; template @@ -15,9 +17,11 @@ struct concept_check enum { instantiate = sizeof((((Model*)0)->~Model()), 3) }; }; -# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ - enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - boost::concept_check::instantiate \ +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + enum \ + { \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + boost::concept_check::instantiate \ } } // namespace boost::concept_checking diff --git a/include/boost/concept_check/Attic/general.hpp b/include/boost/concept_check/Attic/general.hpp index cd09fb0..f9e0274 100755 --- a/include/boost/concept_check/Attic/general.hpp +++ b/include/boost/concept_check/Attic/general.hpp @@ -4,52 +4,38 @@ #ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP # define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# include +# include + # ifdef BOOST_OLD_CONCEPT_SUPPORT # include # include # endif - -// This implementation works on GCC and Comeau, but has actually been -// fairly carefully tuned to work on GCC versions starting with -// gcc-2.95.x. If you're trying to get an additional compiler to pass -// the tests you might consider breaking out a separate gcc.hpp and -// starting over on the general case. +// This implementation works on Comeau and GCC, all the way back to +// 2.95 namespace boost { - namespace concept_checking + template + struct concept_check_; + + namespace concept_checking { template struct instantiate {}; } - template struct concept_check_; - - template - void concept_check_failed() - { - ((Model*)0)->~Model(); - } - template struct concept_check { - concept_checking::instantiate > x; - enum { instantiate = 1 }; + static void failed() { ((Model*)0)->~Model(); } }; # ifdef BOOST_OLD_CONCEPT_SUPPORT - - template - void constraint_check_failed() - { - ((Model*)0)->constraints(); - } template struct constraint_check { - concept_checking::instantiate > x; - enum { instantiate = 1 }; + static void failed() { ((Model*)0)->constraints(); } }; template @@ -69,14 +55,12 @@ namespace boost {}; # endif - - // Usage, in class or function context: - // - // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); -# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ - enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - ::boost::concept_check_::instantiate \ - } + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + typedef boost::concept_checking::instantiate< \ + &boost::concept_check_::failed> \ + BOOST_PP_CAT(boost_concept_check,__LINE__) + } #endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/include/boost/concept_check/Attic/msvc.hpp b/include/boost/concept_check/Attic/msvc.hpp index 3968469..2edcd28 100755 --- a/include/boost/concept_check/Attic/msvc.hpp +++ b/include/boost/concept_check/Attic/msvc.hpp @@ -4,6 +4,8 @@ #ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP # define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# include + # ifdef BOOST_OLD_CONCEPT_SUPPORT # include # include @@ -17,6 +19,7 @@ namespace boost template struct concept_check_ { + ~concept_check_(); virtual void failed(Model* x) { x->~Model(); @@ -52,7 +55,9 @@ namespace boost template struct concept_check : concept_checking::concept_check_ - {}; + { + ~concept_check(); + }; # endif @@ -68,9 +73,11 @@ namespace boost : concept_check { }; -# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ - enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - sizeof(::boost::concept_check) \ +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + enum \ + { \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept_check) \ } # else @@ -79,9 +86,11 @@ namespace boost concept_check concept_check_(void(*)(Model)); -# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ - enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - sizeof(::boost::concept_check_((void(*) ModelInParens)0)) \ +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + enum \ + { \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept_check_((ModelFnPtr)0)) \ } # endif diff --git a/include/boost/concept_check/assert.hpp b/include/boost/concept_check/assert.hpp new file mode 100755 index 0000000..81bcc51 --- /dev/null +++ b/include/boost/concept_check/assert.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_ASSERT_DWA2006430_HPP +# define BOOST_CONCEPT_CHECK_ASSERT_DWA2006430_HPP + +# include +# include + +// The old protocol used a constraints() member function in concept +// checking classes. If the compiler supports SFINAE, we can detect +// that function and seamlessly support the old concept checking +// classes. In this release, backward compatibility with the old +// concept checking classes is enabled by default, where available. +// The old protocol is deprecated, though, and backward compatibility +// will no longer be the default in the next release. + +# if !defined(BOOST_NO_OLD_CONCEPT_SUPPORT) \ + && !defined(BOOST_NO_SFINAE) \ + && !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4)) + +// Note: gcc-3.3.x had no member function pointer SFINAE +# define BOOST_OLD_CONCEPT_SUPPORT + +# endif + +# ifdef BOOST_MSVC +# include +# elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# include +# else +# include +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); + // +# define BOOST_CONCEPT_ASSERT(ModelInParens) \ + BOOST_CONCEPT_ASSERT_FN(void(*)ModelInParens) + +#endif // BOOST_CONCEPT_CHECK_ASSERT_DWA2006430_HPP diff --git a/include/boost/concept_check/where.hpp b/include/boost/concept_check/where.hpp new file mode 100755 index 0000000..c6a6248 --- /dev/null +++ b/include/boost/concept_check/where.hpp @@ -0,0 +1,50 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_WHERE_DWA2006430_HPP +# define BOOST_CONCEPT_CHECK_WHERE_DWA2006430_HPP + +# include +# include +# include + +namespace boost { + +template +struct where : More +{ +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typedef typename More::type type; +# endif + BOOST_CONCEPT_ASSERT_FN(ModelFn); +}; + +#define BOOST_CONCEPT_WHERE_OPEN(r,data,t) ::boost::where + +#if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300) + +# define BOOST_CONCEPT_WHERE(models, result) \ + typename ::boost::parameter::aux::unaryfunptr_arg_type::type + +#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + +// Same thing as below without the initial typename +# define BOOST_CONCEPT_WHERE(models, result) \ + BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \ + ::boost::parameter::aux::unaryfunptr_arg_type \ + BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type + +#else + +// This just ICEs on MSVC6 :( +# define BOOST_CONCEPT_WHERE(models, result) \ + typename BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \ + ::boost::parameter::aux::unaryfunptr_arg_type \ + BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type + +#endif + +} // namespace boost::concept_check + +#endif // BOOST_CONCEPT_CHECK_WHERE_DWA2006430_HPP diff --git a/where.cpp b/where.cpp new file mode 100755 index 0000000..a8d1b8e --- /dev/null +++ b/where.cpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include +#undef NDEBUG +#include "fake_sort.hpp" + +int main() +{ + std::vector v; + fake_sort(v.begin(), v.end()); + return 0; +} diff --git a/where_fail.cpp b/where_fail.cpp new file mode 100755 index 0000000..6c10862 --- /dev/null +++ b/where_fail.cpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#include +#undef NDEBUG +#include "fake_sort.hpp" + +int main() +{ + std::list v; + fake_sort(v.begin(), v.end()); + return 0; +} From 8c32f7a5e259c50b749b795a5201b966d25965f3 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 1 May 2006 13:17:48 +0000 Subject: [PATCH 07/25] Added missing value_type to InputIteratorConcept Improved idiomatic fake_sort [SVN r33889] --- fake_sort.hpp | 19 ++++++++++++------- include/boost/concept_check.hpp | 10 +++++----- where.cpp | 2 +- where_fail.cpp | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/fake_sort.hpp b/fake_sort.hpp index e96504f..8f48f06 100755 --- a/fake_sort.hpp +++ b/fake_sort.hpp @@ -8,15 +8,20 @@ # include # include -template -BOOST_CONCEPT_WHERE( - ((boost::Mutable_RandomAccessIteratorConcept)) - ((boost::LessThanComparableConcept::value_type>)) - - , (void)) -fake_sort(RanIter,RanIter) +namespace fake { + using namespace boost; + + template + BOOST_CONCEPT_WHERE( + ((Mutable_RandomAccessIteratorConcept)) + ((LessThanComparableConcept::value_type>)) + + , (void)) + sort(RanIter,RanIter) + { + } } #endif // BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 37f435e..c89983e 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -462,9 +462,8 @@ namespace boost : AssignableConcept , EqualityComparableConcept { - // require iterator_traits typedef's + typedef typename boost::detail::iterator_traits::value_type value_type; typedef typename boost::detail::iterator_traits::difference_type difference_type; - // Hmm, the following is a bit fragile 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; @@ -591,9 +590,10 @@ namespace boost : RandomAccessIteratorConcept , Mutable_BidirectionalIteratorConcept { - ~Mutable_RandomAccessIteratorConcept() { - i[n] = *i; // require element access and assignment - } + ~Mutable_RandomAccessIteratorConcept() + { + i[n] = *i; // require element access and assignment + } private: TT i; typename boost::detail::iterator_traits::difference_type n; diff --git a/where.cpp b/where.cpp index a8d1b8e..dfbfd02 100755 --- a/where.cpp +++ b/where.cpp @@ -8,6 +8,6 @@ int main() { std::vector v; - fake_sort(v.begin(), v.end()); + fake::sort(v.begin(), v.end()); return 0; } diff --git a/where_fail.cpp b/where_fail.cpp index 6c10862..e56b40f 100755 --- a/where_fail.cpp +++ b/where_fail.cpp @@ -8,6 +8,6 @@ int main() { std::list v; - fake_sort(v.begin(), v.end()); + fake::sort(v.begin(), v.end()); return 0; } From f00741c14f86cd0c5600b8f296e81b0b999c8c53 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 1 May 2006 18:25:20 +0000 Subject: [PATCH 08/25] Moved library specifics out of boost/concept_check and into boost/concept. Moved implementation details into boost/concept/detail. Improved error messages by renaming has_constraints not_satisfied. [SVN r33893] --- .../{concept_check => concept}/assert.hpp | 12 +-- .../Attic => concept/detail}/borland.hpp | 16 +-- include/boost/concept/detail/general.hpp | 66 +++++++++++++ .../boost/concept/detail/has_constraints.hpp | 40 ++++++++ include/boost/concept/detail/msvc.hpp | 88 +++++++++++++++++ .../{concept_check => concept}/where.hpp | 8 +- include/boost/concept_check.hpp | 4 +- include/boost/concept_check/Attic/general.hpp | 66 ------------- .../concept_check/Attic/has_constraints.hpp | 31 ------ include/boost/concept_check/Attic/msvc.hpp | 99 ------------------- 10 files changed, 214 insertions(+), 216 deletions(-) rename include/boost/{concept_check => concept}/assert.hpp (83%) rename include/boost/{concept_check/Attic => concept/detail}/borland.hpp (63%) create mode 100755 include/boost/concept/detail/general.hpp create mode 100755 include/boost/concept/detail/has_constraints.hpp create mode 100755 include/boost/concept/detail/msvc.hpp rename include/boost/{concept_check => concept}/where.hpp (89%) delete mode 100755 include/boost/concept_check/Attic/general.hpp delete mode 100755 include/boost/concept_check/Attic/has_constraints.hpp delete mode 100755 include/boost/concept_check/Attic/msvc.hpp diff --git a/include/boost/concept_check/assert.hpp b/include/boost/concept/assert.hpp similarity index 83% rename from include/boost/concept_check/assert.hpp rename to include/boost/concept/assert.hpp index 81bcc51..8d689ea 100755 --- a/include/boost/concept_check/assert.hpp +++ b/include/boost/concept/assert.hpp @@ -1,8 +1,8 @@ // Copyright David Abrahams 2006. 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) -#ifndef BOOST_CONCEPT_CHECK_ASSERT_DWA2006430_HPP -# define BOOST_CONCEPT_CHECK_ASSERT_DWA2006430_HPP +#ifndef BOOST_CONCEPT_ASSERT_DWA2006430_HPP +# define BOOST_CONCEPT_ASSERT_DWA2006430_HPP # include # include @@ -25,11 +25,11 @@ # endif # ifdef BOOST_MSVC -# include +# include # elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# include +# include # else -# include +# include # endif // Usage, in class or function context: @@ -39,4 +39,4 @@ # define BOOST_CONCEPT_ASSERT(ModelInParens) \ BOOST_CONCEPT_ASSERT_FN(void(*)ModelInParens) -#endif // BOOST_CONCEPT_CHECK_ASSERT_DWA2006430_HPP +#endif // BOOST_CONCEPT_ASSERT_DWA2006430_HPP diff --git a/include/boost/concept_check/Attic/borland.hpp b/include/boost/concept/detail/borland.hpp similarity index 63% rename from include/boost/concept_check/Attic/borland.hpp rename to include/boost/concept/detail/borland.hpp index f82c1c8..59fec55 100755 --- a/include/boost/concept_check/Attic/borland.hpp +++ b/include/boost/concept/detail/borland.hpp @@ -1,18 +1,18 @@ // Copyright David Abrahams 2006. 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) -#ifndef BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP -# define BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP +#ifndef BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP +# define BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP # include -namespace boost { +namespace boost { namespace concept { template -struct concept_check; +struct require; template -struct concept_check +struct require { enum { instantiate = sizeof((((Model*)0)->~Model()), 3) }; }; @@ -21,9 +21,9 @@ struct concept_check enum \ { \ BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - boost::concept_check::instantiate \ + boost::concept::require::instantiate \ } -} // namespace boost::concept_checking +}} // namespace boost::concept -#endif // BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP +#endif // BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP diff --git a/include/boost/concept/detail/general.hpp b/include/boost/concept/detail/general.hpp new file mode 100755 index 0000000..f36f9c4 --- /dev/null +++ b/include/boost/concept/detail/general.hpp @@ -0,0 +1,66 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP +# define BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP + +# include + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + +// This implementation works on Comeau and GCC, all the way back to +// 2.95 +namespace boost { namespace concept { + +template +struct requirement_; + +namespace detail +{ + template struct instantiate {}; +} + +template +struct requirement +{ + static void failed() { ((Model*)0)->~Model(); } +}; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + +template +struct constraint +{ + static void failed() { ((Model*)0)->constraints(); } +}; + +template +struct requirement_ + : mpl::if_< + concept::not_satisfied + , constraint + , requirement + >::type +{}; + +# else + +// For GCC-2.x, these can't have exactly the same name +template +struct requirement_ + : requirement +{}; + +# endif + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + typedef ::boost::concept::detail::instantiate< \ + &::boost::concept::requirement_::failed> \ + BOOST_PP_CAT(boost_concept_check,__LINE__) + +}} + +#endif // BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP diff --git a/include/boost/concept/detail/has_constraints.hpp b/include/boost/concept/detail/has_constraints.hpp new file mode 100755 index 0000000..7ffbb24 --- /dev/null +++ b/include/boost/concept/detail/has_constraints.hpp @@ -0,0 +1,40 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP +# define BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP + +# include + +namespace boost { namespace concept { + +namespace detail +{ + +// Here we implement the metafunction that detects whether a +// constraints metafunction exists + typedef char yes; + typedef char (&no)[2]; + + template + struct wrap_constraints {}; + + template + inline yes has_constraints_(Model*, wrap_constraints* = 0); + inline no has_constraints_(...); +} + +// This would be called "detail::has_constraints," but it has a strong +// tendency to show up in error messages. +template +struct not_satisfied +{ + BOOST_STATIC_CONSTANT( + bool + , value = sizeof( detail::has_constraints_((Model*)0) ) == sizeof(detail::yes) ); + typedef mpl::bool_ type; +}; + +}} // namespace boost::concept::detail + +#endif // BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP diff --git a/include/boost/concept/detail/msvc.hpp b/include/boost/concept/detail/msvc.hpp new file mode 100755 index 0000000..7165d44 --- /dev/null +++ b/include/boost/concept/detail/msvc.hpp @@ -0,0 +1,88 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# include + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +namespace boost { namespace concept { + +template +struct check +{ + virtual void failed(Model* x) + { + x->~Model(); + } +}; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + +namespace detail +{ + // No need for a virtual function here, since evaluatiing + // not_satisfied below will have already instantiated the + // constraints() member. + struct constraint {}; +} +template +struct require + : mpl::if_c< + not_satisfied::value + , detail::constraint + , check + >::type +{}; + +# else + +template +struct require + : check +{}; + +# endif + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1310) + +// +// The iterator library sees some really strange errors unless we +// use partial specialization to extract the model type with +// msvc-7.1 +// +template +struct require + : require +{}; + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ +enum \ +{ \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept::require) \ +} + +# else // Not vc-7.1 + +template +require +require_(void(*)(Model)); + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ +enum \ +{ \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept::require_((ModelFnPtr)0)) \ +} + +# endif +}} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/include/boost/concept_check/where.hpp b/include/boost/concept/where.hpp similarity index 89% rename from include/boost/concept_check/where.hpp rename to include/boost/concept/where.hpp index c6a6248..eec01b7 100755 --- a/include/boost/concept_check/where.hpp +++ b/include/boost/concept/where.hpp @@ -1,11 +1,11 @@ // Copyright David Abrahams 2006. 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) -#ifndef BOOST_CONCEPT_CHECK_WHERE_DWA2006430_HPP -# define BOOST_CONCEPT_CHECK_WHERE_DWA2006430_HPP +#ifndef BOOST_CONCEPT_WHERE_DWA2006430_HPP +# define BOOST_CONCEPT_WHERE_DWA2006430_HPP # include -# include +# include # include namespace boost { @@ -47,4 +47,4 @@ struct where : More } // namespace boost::concept_check -#endif // BOOST_CONCEPT_CHECK_WHERE_DWA2006430_HPP +#endif // BOOST_CONCEPT_WHERE_DWA2006430_HPP diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index c89983e..2169a8d 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -15,7 +15,7 @@ #ifndef BOOST_CONCEPT_CHECKS_HPP # define BOOST_CONCEPT_CHECKS_HPP -# include +# include # include # include @@ -35,7 +35,7 @@ namespace boost // template - inline void function_requires(BOOST_EXPLICIT_TEMPLATE_TYPE(Model)) + inline void function_requires(Model* = 0) { BOOST_CONCEPT_ASSERT((Model)); } diff --git a/include/boost/concept_check/Attic/general.hpp b/include/boost/concept_check/Attic/general.hpp deleted file mode 100755 index f9e0274..0000000 --- a/include/boost/concept_check/Attic/general.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright David Abrahams 2006. 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) -#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP -# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP - -# include -# include - -# ifdef BOOST_OLD_CONCEPT_SUPPORT -# include -# include -# endif - -// This implementation works on Comeau and GCC, all the way back to -// 2.95 -namespace boost -{ - template - struct concept_check_; - - namespace concept_checking - { - template struct instantiate {}; - } - - template - struct concept_check - { - static void failed() { ((Model*)0)->~Model(); } - }; - -# ifdef BOOST_OLD_CONCEPT_SUPPORT - - template - struct constraint_check - { - static void failed() { ((Model*)0)->constraints(); } - }; - - template - struct concept_check_ - : mpl::if_c< - concept_checking::has_constraints::value - , constraint_check - , concept_check - >::type - {}; - -# else - - template - struct concept_check_ - : concept_check - {}; - -# endif - -# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ - typedef boost::concept_checking::instantiate< \ - &boost::concept_check_::failed> \ - BOOST_PP_CAT(boost_concept_check,__LINE__) - -} - -#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/include/boost/concept_check/Attic/has_constraints.hpp b/include/boost/concept_check/Attic/has_constraints.hpp deleted file mode 100755 index e19f664..0000000 --- a/include/boost/concept_check/Attic/has_constraints.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright David Abrahams 2006. 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) -#ifndef BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP -# define BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP - -namespace boost { namespace concept_checking { - -// Here we implement the "metafunction" that detects whether a -// constraints metafunction exists -typedef char yes; -typedef char (&no)[2]; - -template -struct wrap_constraints {}; - -template -inline yes has_constraints_(Model*, wrap_constraints* = 0); -inline no has_constraints_(...); - -template -struct has_constraints -{ - BOOST_STATIC_CONSTANT( - bool - , value = sizeof( concept_checking::has_constraints_((Model*)0) ) == 1 ); -}; - -}} // namespace boost::concept_checking - -#endif // BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP diff --git a/include/boost/concept_check/Attic/msvc.hpp b/include/boost/concept_check/Attic/msvc.hpp deleted file mode 100755 index 2edcd28..0000000 --- a/include/boost/concept_check/Attic/msvc.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright David Abrahams 2006. 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) -#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP -# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP - -# include - -# ifdef BOOST_OLD_CONCEPT_SUPPORT -# include -# include -# endif - - -namespace boost -{ - namespace concept_checking - { - template - struct concept_check_ - { - ~concept_check_(); - virtual void failed(Model* x) - { - x->~Model(); - } - }; - } - -# ifdef BOOST_OLD_CONCEPT_SUPPORT - - namespace concept_checking - { - template - struct constraint_check - { - virtual void failed(Model* x) - { - x->constraints(); - } - }; - } - - template - struct concept_check - : mpl::if_c< - concept_checking::has_constraints::value - , concept_checking::constraint_check - , concept_checking::concept_check_ - >::type - {}; - -# else - - template - struct concept_check - : concept_checking::concept_check_ - { - ~concept_check(); - }; - -# endif - -# if BOOST_WORKAROUND(BOOST_MSVC, == 1310) - - // - // The iterator library sees some really strange errors unless we - // use partial specialization to extract the model type with - // msvc-7.1 - // - template - struct concept_check - : concept_check - { }; - -# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ - enum \ - { \ - BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - sizeof(::boost::concept_check) \ - } - -# else - - template - concept_check - concept_check_(void(*)(Model)); - -# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ - enum \ - { \ - BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - sizeof(::boost::concept_check_((ModelFnPtr)0)) \ - } - -# endif -} - -#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP From 79017f985a5f853f85194240c42b830b45baf6be Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 1 May 2006 19:40:32 +0000 Subject: [PATCH 09/25] Killed off "Concept" suffixes on Boost concepts. Maintained back-compatibility by using a macro to define XxxxConcept when defining Xxxxx. [SVN r33894] --- Jamfile | 4 + Jamfile.v2 | 2 + class_concept_check_test.cpp | 8 +- class_concept_fail_expected.cpp | 2 +- concept_check.htm | 11 +- concept_check_fail_expected.cpp | 2 +- concept_check_test.cpp | 64 +- fake_sort.hpp | 6 +- function_requires_fail.cpp | 2 +- include/boost/concept/detail/concept_def.hpp | 29 + .../boost/concept/detail/concept_undef.hpp | 5 + include/boost/concept_check.hpp | 637 ++++++++---------- stl_concept_check.cpp | 46 +- stl_concept_covering.cpp | 2 +- 14 files changed, 407 insertions(+), 413 deletions(-) create mode 100755 include/boost/concept/detail/concept_def.hpp create mode 100755 include/boost/concept/detail/concept_undef.hpp diff --git a/Jamfile b/Jamfile index 782ed1a..e16f2a0 100644 --- a/Jamfile +++ b/Jamfile @@ -4,11 +4,15 @@ import testing ; test-suite concept_check : [ run stl_concept_covering.cpp ] + [ run stl_concept_check.cpp ] [ run concept_check_test.cpp ] [ run class_concept_check_test.cpp ] [ compile-fail concept_check_fail_expected.cpp ] [ compile-fail class_concept_fail_expected.cpp ] + [ run where.cpp ] + [ compile-fail where_fail.cpp ] + # Backward compatibility tests [ run old_concept_pass.cpp ] [ compile-fail function_requires_fail.cpp ] diff --git a/Jamfile.v2 b/Jamfile.v2 index 02efb76..251542f 100644 --- a/Jamfile.v2 +++ b/Jamfile.v2 @@ -3,6 +3,7 @@ import testing ; test-suite concept_check : [ run stl_concept_covering.cpp ] + [ run stl_concept_check.cpp ] [ run concept_check_test.cpp ] [ run class_concept_check_test.cpp ] [ compile-fail concept_check_fail_expected.cpp ] @@ -17,3 +18,4 @@ test-suite concept_check [ compile-fail old_concept_function_fail.cpp ] [ compile-fail old_concept_class_fail.cpp ] ; + diff --git a/class_concept_check_test.cpp b/class_concept_check_test.cpp index d99845c..d5512c6 100644 --- a/class_concept_check_test.cpp +++ b/class_concept_check_test.cpp @@ -18,11 +18,11 @@ struct bar { bool operator()(int, char) { return true; } }; class class_requires_test { - BOOST_CONCEPT_ASSERT((boost::EqualityComparableConcept)); + BOOST_CONCEPT_ASSERT((boost::EqualityComparable)); typedef int* int_ptr; typedef const int* const_int_ptr; - BOOST_CONCEPT_ASSERT((boost::EqualOpConcept)); - BOOST_CONCEPT_ASSERT((boost::UnaryFunctionConcept)); -// BOOST_CONCEPT_ASSERT((boost::BinaryFunctionConcept)); + BOOST_CONCEPT_ASSERT((boost::EqualOp)); + BOOST_CONCEPT_ASSERT((boost::UnaryFunction)); + BOOST_CONCEPT_ASSERT((boost::BinaryFunction)); }; int diff --git a/class_concept_fail_expected.cpp b/class_concept_fail_expected.cpp index 6cafbd4..74268e3 100644 --- a/class_concept_fail_expected.cpp +++ b/class_concept_fail_expected.cpp @@ -20,7 +20,7 @@ struct foo { }; template class class_requires_test { - BOOST_CONCEPT_ASSERT((boost::EqualityComparableConcept)); + BOOST_CONCEPT_ASSERT((boost::EqualityComparable)); }; int diff --git a/concept_check.htm b/concept_check.htm index 0e55aa8..194b0c2 100644 --- a/concept_check.htm +++ b/concept_check.htm @@ -238,9 +238,9 @@ Library produces):
 boost/concept_check.hpp: In method `void LessThanComparableConcept
-  <_List_iterator<int,int &,int *> >::constraints()':
+  <_List_iterator<int,int &,int *> >::~LessThanComparableConcept()':
 boost/concept_check.hpp:334:   instantiated from `RandomAccessIteratorConcept
-  <_List_iterator<int,int &,int *> >::constraints()'
+  <_List_iterator<int,int &,int *> >::~RandomAccessIteratorConcept()'
 bad_error_eg.cpp:6:   instantiated from `stable_sort<_List_iterator
   <int,int &,int *> >(_List_iterator<int,int &,int *>, 
   _List_iterator<int,int &,int *>)'
@@ -260,10 +260,9 @@ href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
 RandomAccessIterator).
 
  • The error message is now much shorter and does not reveal internal STL functions. -
  • The presence of concept_check.hpp and - constraints() in the error message alerts the user to the - fact that the error lies in the user code and not in the library - implementation. +
  • The presence of concept_check.hpp in the error message + alerts the user to the fact that the error lies in the user code and + not in the library implementation.

    History

    diff --git a/concept_check_fail_expected.cpp b/concept_check_fail_expected.cpp index f213ab5..15bfe7a 100644 --- a/concept_check_fail_expected.cpp +++ b/concept_check_fail_expected.cpp @@ -21,6 +21,6 @@ struct foo { }; int main() { - BOOST_CONCEPT_ASSERT((boost::EqualityComparableConcept)); + BOOST_CONCEPT_ASSERT((boost::EqualityComparable)); return 0; } diff --git a/concept_check_test.cpp b/concept_check_test.cpp index 070988b..f39ced7 100644 --- a/concept_check_test.cpp +++ b/concept_check_test.cpp @@ -25,76 +25,76 @@ main() // Basic Concepts { typedef default_constructible_archetype<> foo; - function_requires< DefaultConstructibleConcept >(); + function_requires< DefaultConstructible >(); } { typedef assignable_archetype<> foo; - function_requires< AssignableConcept >(); + function_requires< Assignable >(); } { typedef copy_constructible_archetype<> foo; - function_requires< CopyConstructibleConcept >(); + function_requires< CopyConstructible >(); } { typedef sgi_assignable_archetype<> foo; - function_requires< SGIAssignableConcept >(); + function_requires< SGIAssignable >(); } { typedef copy_constructible_archetype<> foo; typedef convertible_to_archetype convertible_to_foo; - function_requires< ConvertibleConcept >(); + function_requires< Convertible >(); } { - function_requires< ConvertibleConcept >(); + function_requires< Convertible >(); } { typedef equality_comparable_archetype<> foo; - function_requires< EqualityComparableConcept >(); + function_requires< EqualityComparable >(); } { typedef less_than_comparable_archetype<> foo; - function_requires< LessThanComparableConcept >(); + function_requires< LessThanComparable >(); } { typedef comparable_archetype<> foo; - function_requires< ComparableConcept >(); + function_requires< Comparable >(); } { typedef equal_op_first_archetype<> First; typedef equal_op_second_archetype<> Second; - function_requires< EqualOpConcept >(); + function_requires< EqualOp >(); } { typedef not_equal_op_first_archetype<> First; typedef not_equal_op_second_archetype<> Second; - function_requires< NotEqualOpConcept >(); + function_requires< NotEqualOp >(); } { typedef less_than_op_first_archetype<> First; typedef less_than_op_second_archetype<> Second; - function_requires< LessThanOpConcept >(); + function_requires< LessThanOp >(); } { typedef less_equal_op_first_archetype<> First; typedef less_equal_op_second_archetype<> Second; - function_requires< LessEqualOpConcept >(); + function_requires< LessEqualOp >(); } { typedef greater_than_op_first_archetype<> First; typedef greater_than_op_second_archetype<> Second; - function_requires< GreaterThanOpConcept >(); + function_requires< GreaterThanOp >(); } { typedef greater_equal_op_first_archetype<> First; typedef greater_equal_op_second_archetype<> Second; - function_requires< GreaterEqualOpConcept >(); + function_requires< GreaterEqualOp >(); } { typedef copy_constructible_archetype<> Return; typedef plus_op_first_archetype First; typedef plus_op_second_archetype Second; - function_requires< PlusOpConcept >(); + function_requires< PlusOp >(); } //=========================================================================== @@ -102,70 +102,70 @@ main() { typedef generator_archetype > foo; - function_requires< GeneratorConcept > >(); + function_requires< Generator > >(); } #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION { - function_requires< GeneratorConcept< void_generator_archetype, void > >(); + function_requires< Generator< void_generator_archetype, void > >(); } #endif { typedef unary_function_archetype F; - function_requires< UnaryFunctionConcept >(); + function_requires< UnaryFunction >(); } { typedef binary_function_archetype F; - function_requires< BinaryFunctionConcept >(); + function_requires< BinaryFunction >(); } { typedef unary_predicate_archetype F; - function_requires< UnaryPredicateConcept >(); + function_requires< UnaryPredicate >(); } { typedef binary_predicate_archetype F; - function_requires< BinaryPredicateConcept >(); + function_requires< BinaryPredicate >(); } //=========================================================================== // Iterator Concepts { typedef input_iterator_archetype > Iter; - function_requires< InputIteratorConcept >(); + function_requires< InputIterator >(); } { typedef output_iterator_archetype Iter; - function_requires< OutputIteratorConcept >(); + function_requires< OutputIterator >(); } { typedef input_output_iterator_archetype Iter; - function_requires< InputIteratorConcept >(); - function_requires< OutputIteratorConcept >(); + function_requires< InputIterator >(); + function_requires< OutputIterator >(); } { typedef forward_iterator_archetype > Iter; - function_requires< ForwardIteratorConcept >(); + function_requires< ForwardIterator >(); } { typedef mutable_forward_iterator_archetype > Iter; - function_requires< Mutable_ForwardIteratorConcept >(); + function_requires< Mutable_ForwardIterator >(); } { typedef bidirectional_iterator_archetype > Iter; - function_requires< BidirectionalIteratorConcept >(); + function_requires< BidirectionalIterator >(); } { typedef mutable_bidirectional_iterator_archetype > Iter; - function_requires< Mutable_BidirectionalIteratorConcept >(); + function_requires< Mutable_BidirectionalIterator >(); } { typedef random_access_iterator_archetype > Iter; - function_requires< RandomAccessIteratorConcept >(); + function_requires< RandomAccessIterator >(); } { typedef mutable_random_access_iterator_archetype > Iter; - function_requires< Mutable_RandomAccessIteratorConcept >(); + function_requires< Mutable_RandomAccessIterator >(); } //=========================================================================== diff --git a/fake_sort.hpp b/fake_sort.hpp index 8f48f06..bdac487 100755 --- a/fake_sort.hpp +++ b/fake_sort.hpp @@ -5,7 +5,7 @@ # define BOOST_LIBS_CONCEPT_CHECK_FAKE_SORT_DWA2006430_HPP # include -# include +# include # include namespace fake @@ -14,8 +14,8 @@ namespace fake template BOOST_CONCEPT_WHERE( - ((Mutable_RandomAccessIteratorConcept)) - ((LessThanComparableConcept::value_type>)) + ((Mutable_RandomAccessIterator)) + ((LessThanComparable::value_type>)) , (void)) sort(RanIter,RanIter) diff --git a/function_requires_fail.cpp b/function_requires_fail.cpp index 5c9a4f3..03beaec 100755 --- a/function_requires_fail.cpp +++ b/function_requires_fail.cpp @@ -21,6 +21,6 @@ struct foo { }; int main() { - boost::function_requires< boost::EqualityComparableConcept >(); + boost::function_requires< boost::EqualityComparable >(); return 0; } diff --git a/include/boost/concept/detail/concept_def.hpp b/include/boost/concept/detail/concept_def.hpp new file mode 100755 index 0000000..56ba817 --- /dev/null +++ b/include/boost/concept/detail/concept_def.hpp @@ -0,0 +1,29 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP +# define BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP +# include +# include +# include +#endif // BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP + +// BOOST_concept(SomeName, (p1)(p2)...(pN)) +// +// Expands to "template struct SomeName" +// +// Also defines an equivalent SomeNameConcept for backward compatibility. +// Maybe in the next release we can kill off the "Concept" suffix for good. +# define BOOST_CONCEPT_typename(r, ignored, index, t) \ + BOOST_PP_COMMA_IF(index) typename t + +# define BOOST_concept(name, params) \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename, ~, params) > \ + struct name; \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename, ~, params) > \ + struct BOOST_PP_CAT(name,Concept) : name< BOOST_PP_SEQ_ENUM(params) > \ + { BOOST_PP_CAT(name,Concept)(); }; /* ctor needed to satisfy gcc-3.4.4 */ \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename, ~, params) > \ + struct name + + diff --git a/include/boost/concept/detail/concept_undef.hpp b/include/boost/concept/detail/concept_undef.hpp new file mode 100755 index 0000000..713db89 --- /dev/null +++ b/include/boost/concept/detail/concept_undef.hpp @@ -0,0 +1,5 @@ +// Copyright David Abrahams 2006. 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) +# undef BOOST_concept_typename +# undef BOOST_concept diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 2169a8d..3b43f2c 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -26,6 +26,7 @@ # include # include +# include namespace boost { @@ -57,57 +58,56 @@ namespace boost // // Begin concept definitions // - template - struct IntegerConcept { - ~IntegerConcept() { - x.error_type_must_be_an_integer_type(); - } + BOOST_concept(Integer, (T)) + { + ~Integer() + { + x.error_type_must_be_an_integer_type(); + } private: - T x; + T x; }; - template <> struct IntegerConcept {}; - template <> struct IntegerConcept {}; - template <> struct IntegerConcept {}; - template <> struct IntegerConcept {}; - template <> struct IntegerConcept {}; - template <> struct IntegerConcept {}; - template <> struct IntegerConcept {}; - template <> struct IntegerConcept {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; // etc. - template - struct SignedIntegerConcept { - ~SignedIntegerConcept() { + BOOST_concept(SignedInteger,(T)) { + ~SignedInteger() { x.error_type_must_be_a_signed_integer_type(); } private: T x; }; - template <> struct SignedIntegerConcept { }; - template <> struct SignedIntegerConcept {}; - template <> struct SignedIntegerConcept {}; - template <> struct SignedIntegerConcept {}; + template <> struct SignedInteger { }; + template <> struct SignedInteger {}; + template <> struct SignedInteger {}; + template <> struct SignedInteger {}; # if defined(BOOST_HAS_LONG_LONG) - template <> struct SignedIntegerConcept< ::boost::long_long_type> {}; + template <> struct SignedInteger< ::boost::long_long_type> {}; // etc. #endif - template - struct UnsignedIntegerConcept { - ~UnsignedIntegerConcept() { + BOOST_concept(UnsignedInteger,(T)) { + ~UnsignedInteger() { x.error_type_must_be_an_unsigned_integer_type(); } private: T x; }; - template <> struct UnsignedIntegerConcept {}; - template <> struct UnsignedIntegerConcept {}; - template <> struct UnsignedIntegerConcept {}; - template <> struct UnsignedIntegerConcept {}; + template <> struct UnsignedInteger {}; + template <> struct UnsignedInteger {}; + template <> struct UnsignedInteger {}; + template <> struct UnsignedInteger {}; # if defined(BOOST_HAS_LONG_LONG) - template <> struct UnsignedIntegerConcept< ::boost::ulong_long_type> {}; + template <> struct UnsignedInteger< ::boost::ulong_long_type> {}; // etc. #endif @@ -116,19 +116,17 @@ namespace boost //=========================================================================== // Basic Concepts - template - struct DefaultConstructibleConcept + BOOST_concept(DefaultConstructible,(TT)) { - ~DefaultConstructibleConcept() { + ~DefaultConstructible() { TT a; // require default constructor ignore_unused_variable_warning(a); } }; - template - struct AssignableConcept + BOOST_concept(Assignable,(TT)) { - ~AssignableConcept() { + ~Assignable() { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator #endif @@ -144,10 +142,9 @@ namespace boost TT a; }; - template - struct CopyConstructibleConcept + BOOST_concept(CopyConstructible,(TT)) { - ~CopyConstructibleConcept() { + ~CopyConstructible() { TT a(b); // require copy constructor TT* ptr = &a; // require address of operator const_constraints(a); @@ -164,10 +161,9 @@ namespace boost }; // The SGI STL version of Assignable requires copy constructor and operator= - template - struct SGIAssignableConcept + BOOST_concept(SGIAssignable,(TT)) { - ~SGIAssignableConcept() { + ~SGIAssignable() { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator @@ -186,10 +182,9 @@ namespace boost TT a; }; - template - struct ConvertibleConcept + BOOST_concept(Convertible,(X)(Y)) { - ~ConvertibleConcept() { + ~Convertible() { Y y = x; ignore_unused_variable_warning(y); } @@ -212,10 +207,9 @@ namespace boost ignore_unused_variable_warning(x); } - template - struct EqualityComparableConcept + BOOST_concept(EqualityComparable,(TT)) { - ~EqualityComparableConcept() { + ~EqualityComparable() { require_boolean_expr(a == b); require_boolean_expr(a != b); } @@ -223,10 +217,9 @@ namespace boost TT a, b; }; - template - struct LessThanComparableConcept + BOOST_concept(LessThanComparable,(TT)) { - ~LessThanComparableConcept() { + ~LessThanComparable() { require_boolean_expr(a < b); } private: @@ -234,10 +227,9 @@ namespace boost }; // This is equivalent to SGI STL's LessThanComparable. - template - struct ComparableConcept + BOOST_concept(Comparable,(TT)) { - ~ComparableConcept() { + ~Comparable() { require_boolean_expr(a < b); require_boolean_expr(a > b); require_boolean_expr(a <= b); @@ -248,49 +240,44 @@ namespace boost }; #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ - template \ - struct NAME { \ - ~NAME() { (void)constraints_(); } \ + BOOST_concept(NAME, (First)(Second)) \ + { \ + ~NAME() { (void)constraints_(); } \ private: \ - bool constraints_() { \ - return a OP b; \ - } \ - First a; \ - Second b; \ + bool 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; \ - } \ - First a; \ - Second b; \ + BOOST_concept(NAME, (Ret)(First)(Second)) \ + { \ + ~NAME() { (void)constraints_(); } \ + private: \ + Ret constraints_() { return a OP b; } \ + First a; \ + Second b; \ } - BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept); - BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOpConcept); - BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOpConcept); - BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOpConcept); - BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOpConcept); - BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOpConcept); + 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(+, PlusOpConcept); - BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOpConcept); - BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOpConcept); - BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOpConcept); - BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOpConcept); + 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 - template - struct GeneratorConcept + BOOST_concept(Generator,(Func)(Return)) { - ~GeneratorConcept() { test(is_void()); } + ~Generator() { test(is_void()); } private: void test(boost::mpl::false_) @@ -309,10 +296,9 @@ namespace boost }; - template - struct UnaryFunctionConcept + BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) { - ~UnaryFunctionConcept() { test(is_void()); } + ~UnaryFunction() { test(is_void()); } private: void test(boost::mpl::false_) @@ -331,10 +317,9 @@ namespace boost Arg arg; }; - template - struct BinaryFunctionConcept + BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) { - ~BinaryFunctionConcept() { test(is_void()); } + ~BinaryFunction() { test(is_void()); } private: void test(boost::mpl::false_) { @@ -354,10 +339,9 @@ namespace boost Return r; }; - template - struct UnaryPredicateConcept + BOOST_concept(UnaryPredicate,(Func)(Arg)) { - ~UnaryPredicateConcept() { + ~UnaryPredicate() { require_boolean_expr(f(arg)); // require operator() returning bool } private: @@ -365,10 +349,9 @@ namespace boost Arg arg; }; - template - struct BinaryPredicateConcept + BOOST_concept(BinaryPredicate,(Func)(First)(Second)) { - ~BinaryPredicateConcept() { + ~BinaryPredicate() { require_boolean_expr(f(a, b)); // require operator() returning bool } private: @@ -378,11 +361,10 @@ namespace boost }; // use this when functor is used inside a container class like std::set - template - struct Const_BinaryPredicateConcept - : BinaryPredicateConcept + BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) + : BinaryPredicate { - ~Const_BinaryPredicateConcept() { + ~Const_BinaryPredicate() { const_constraints(f); } private: @@ -395,35 +377,32 @@ namespace boost Second b; }; - template - struct AdaptableGeneratorConcept - : GeneratorConcept + BOOST_concept(AdaptableGenerator,(Func)(Return)) + : Generator { typedef typename Func::result_type result_type; - ~AdaptableGeneratorConcept() + ~AdaptableGenerator() { - BOOST_CONCEPT_ASSERT((ConvertibleConcept)); + BOOST_CONCEPT_ASSERT((Convertible)); } }; - template - struct AdaptableUnaryFunctionConcept - : UnaryFunctionConcept + BOOST_concept(AdaptableUnaryFunction,(Func)(Return)(Arg)) + : UnaryFunction { typedef typename Func::argument_type argument_type; typedef typename Func::result_type result_type; - ~AdaptableUnaryFunctionConcept() + ~AdaptableUnaryFunction() { - BOOST_CONCEPT_ASSERT((ConvertibleConcept)); - BOOST_CONCEPT_ASSERT((ConvertibleConcept)); + BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_CONCEPT_ASSERT((Convertible)); } }; - template - struct AdaptableBinaryFunctionConcept - : BinaryFunctionConcept< + BOOST_concept(AdaptableBinaryFunction,(Func)(Return)(First)(Second)) + : BinaryFunction< Func , typename Func::result_type , typename Func::first_argument_type @@ -434,33 +413,30 @@ namespace boost typedef typename Func::second_argument_type second_argument_type; typedef typename Func::result_type result_type; - ~AdaptableBinaryFunctionConcept() + ~AdaptableBinaryFunction() { - BOOST_CONCEPT_ASSERT((ConvertibleConcept)); - BOOST_CONCEPT_ASSERT((ConvertibleConcept)); - BOOST_CONCEPT_ASSERT((ConvertibleConcept)); + BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_CONCEPT_ASSERT((Convertible)); } }; - template - struct AdaptablePredicateConcept - : UnaryPredicateConcept - , AdaptableUnaryFunctionConcept + BOOST_concept(AdaptablePredicate,(Func)(Arg)) + : UnaryPredicate + , AdaptableUnaryFunction {}; - template - struct AdaptableBinaryPredicateConcept - : BinaryPredicateConcept - , AdaptableBinaryFunctionConcept + BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second)) + : BinaryPredicate + , AdaptableBinaryFunction {}; //=========================================================================== // Iterator Concepts - template - struct InputIteratorConcept - : AssignableConcept - , EqualityComparableConcept + BOOST_concept(InputIterator,(TT)) + : Assignable + , EqualityComparable { typedef typename boost::detail::iterator_traits::value_type value_type; typedef typename boost::detail::iterator_traits::difference_type difference_type; @@ -468,10 +444,10 @@ namespace boost typedef typename boost::detail::iterator_traits::pointer pointer; typedef typename boost::detail::iterator_traits::iterator_category iterator_category; - ~InputIteratorConcept() + ~InputIterator() { - BOOST_CONCEPT_ASSERT((SignedIntegerConcept)); - BOOST_CONCEPT_ASSERT((ConvertibleConcept)); + BOOST_CONCEPT_ASSERT((SignedInteger)); + BOOST_CONCEPT_ASSERT((Convertible)); TT j(i); (void)*i; // require dereference operator @@ -482,11 +458,10 @@ namespace boost TT i; }; - template - struct OutputIteratorConcept - : AssignableConcept + BOOST_concept(OutputIterator,(TT)(ValueT)) + : Assignable { - ~OutputIteratorConcept() { + ~OutputIterator() { ++i; // require preincrement operator i++; // require postincrement operator @@ -497,18 +472,17 @@ namespace boost ValueT t; }; - template - struct ForwardIteratorConcept - : InputIteratorConcept + BOOST_concept(ForwardIterator,(TT)) + : InputIterator { - ~ForwardIteratorConcept() + ~ForwardIterator() { - BOOST_CONCEPT_ASSERT((ConvertibleConcept< - BOOST_DEDUCED_TYPENAME ForwardIteratorConcept::iterator_category + BOOST_CONCEPT_ASSERT((Convertible< + BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category , std::forward_iterator_tag >)); - typename InputIteratorConcept::reference r = *i; + typename InputIterator::reference r = *i; ignore_unused_variable_warning(r); } @@ -516,25 +490,23 @@ namespace boost TT i; }; - template - struct Mutable_ForwardIteratorConcept - : ForwardIteratorConcept + BOOST_concept(Mutable_ForwardIterator,(TT)) + : ForwardIterator { - ~Mutable_ForwardIteratorConcept() { + ~Mutable_ForwardIterator() { *i++ = *i; // require postincrement and assignment } private: TT i; }; - template - struct BidirectionalIteratorConcept - : ForwardIteratorConcept + BOOST_concept(BidirectionalIterator,(TT)) + : ForwardIterator { - ~BidirectionalIteratorConcept() + ~BidirectionalIterator() { - BOOST_CONCEPT_ASSERT((ConvertibleConcept< - BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::iterator_category + BOOST_CONCEPT_ASSERT((Convertible< + BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category , std::bidirectional_iterator_tag >)); @@ -545,12 +517,11 @@ namespace boost TT i; }; - template - struct Mutable_BidirectionalIteratorConcept - : BidirectionalIteratorConcept - , Mutable_ForwardIteratorConcept + BOOST_concept(Mutable_BidirectionalIterator,(TT)) + : BidirectionalIterator + , Mutable_ForwardIterator { - ~Mutable_BidirectionalIteratorConcept() + ~Mutable_BidirectionalIterator() { *i-- = *i; // require postdecrement and assignment } @@ -559,15 +530,14 @@ namespace boost }; - template - struct RandomAccessIteratorConcept - : BidirectionalIteratorConcept - , ComparableConcept + BOOST_concept(RandomAccessIterator,(TT)) + : BidirectionalIterator + , Comparable { - ~RandomAccessIteratorConcept() + ~RandomAccessIterator() { - BOOST_CONCEPT_ASSERT((ConvertibleConcept< - BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::iterator_category + BOOST_CONCEPT_ASSERT((Convertible< + BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category , std::random_access_iterator_tag >)); @@ -585,12 +555,11 @@ namespace boost typename boost::detail::iterator_traits::difference_type n; }; - template - struct Mutable_RandomAccessIteratorConcept - : RandomAccessIteratorConcept - , Mutable_BidirectionalIteratorConcept + BOOST_concept(Mutable_RandomAccessIterator,(TT)) + : RandomAccessIterator + , Mutable_BidirectionalIterator { - ~Mutable_RandomAccessIteratorConcept() + ~Mutable_RandomAccessIterator() { i[n] = *i; // require element access and assignment } @@ -600,53 +569,51 @@ namespace boost }; //=========================================================================== - // Container Concepts + // Container s - template - struct ContainerConcept - : AssignableConcept + BOOST_concept(Container,(C)) + : Assignable { - typedef typename Container::value_type value_type; - typedef typename Container::difference_type difference_type; - typedef typename Container::size_type size_type; - typedef typename Container::const_reference const_reference; - typedef typename Container::const_pointer const_pointer; - typedef typename Container::const_iterator const_iterator; + 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; - ~ContainerConcept() + ~Container() { - BOOST_CONCEPT_ASSERT((InputIteratorConcept)); + BOOST_CONCEPT_ASSERT((InputIterator)); const_constraints(c); } private: - void const_constraints(const Container& cc) { + void const_constraints(const C& cc) { i = cc.begin(); i = cc.end(); n = cc.size(); n = cc.max_size(); b = cc.empty(); } - Container c; + C c; bool b; const_iterator i; size_type n; }; - template - struct Mutable_ContainerConcept - : ContainerConcept + BOOST_concept(Mutable_Container,(C)) + : Container { - typedef typename Container::reference reference; - typedef typename Container::iterator iterator; - typedef typename Container::pointer pointer; + typedef typename C::reference reference; + typedef typename C::iterator iterator; + typedef typename C::pointer pointer; - ~Mutable_ContainerConcept() + ~Mutable_Container() { BOOST_CONCEPT_ASSERT(( - AssignableConcept)); + Assignable)); - BOOST_CONCEPT_ASSERT((InputIteratorConcept)); + BOOST_CONCEPT_ASSERT((InputIterator)); i = c.begin(); i = c.end(); @@ -655,143 +622,137 @@ namespace boost private: iterator i; - Container c, c2; + C c, c2; }; - template - struct ForwardContainerConcept - : ContainerConcept + BOOST_concept(ForwardContainer,(C)) + : Container { - ~ForwardContainerConcept() + ~ForwardContainer() { BOOST_CONCEPT_ASSERT(( - ForwardIteratorConcept< - typename ForwardContainerConcept::const_iterator + ForwardIterator< + typename ForwardContainer::const_iterator >)); } }; - template - struct Mutable_ForwardContainerConcept - : ForwardContainerConcept - , Mutable_ContainerConcept + BOOST_concept(Mutable_ForwardContainer,(C)) + : ForwardContainer + , Mutable_Container { - ~Mutable_ForwardContainerConcept() + ~Mutable_ForwardContainer() { BOOST_CONCEPT_ASSERT(( - Mutable_ForwardIteratorConcept< - typename Mutable_ForwardContainerConcept::iterator + Mutable_ForwardIterator< + typename Mutable_ForwardContainer::iterator >)); } }; - template - struct ReversibleContainerConcept - : ForwardContainerConcept + BOOST_concept(ReversibleContainer,(C)) + : ForwardContainer { typedef typename - ReversibleContainer::const_reverse_iterator + C::const_reverse_iterator const_reverse_iterator; - ~ReversibleContainerConcept() + ~ReversibleContainer() { BOOST_CONCEPT_ASSERT(( - BidirectionalIteratorConcept< - typename ReversibleContainerConcept::const_iterator>)); + BidirectionalIterator< + typename ReversibleContainer::const_iterator>)); - BOOST_CONCEPT_ASSERT((BidirectionalIteratorConcept)); + BOOST_CONCEPT_ASSERT((BidirectionalIterator)); const_constraints(c); } private: - void const_constraints(const ReversibleContainer& cc) + void const_constraints(const C& cc) { const_reverse_iterator i = cc.rbegin(); i = cc.rend(); } - ReversibleContainer c; + C c; }; - template - struct Mutable_ReversibleContainerConcept - : Mutable_ForwardContainerConcept - , ReversibleContainerConcept + BOOST_concept(Mutable_ReversibleContainer,(C)) + : Mutable_ForwardContainer + , ReversibleContainer { - typedef typename ReversibleContainer::iterator iterator; - typedef typename ReversibleContainer::reverse_iterator reverse_iterator; - - ~Mutable_ReversibleContainerConcept() + typedef typename C::reverse_iterator reverse_iterator; + + ~Mutable_ReversibleContainer() { - BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIteratorConcept)); - BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIteratorConcept)); - reverse_iterator i = c.rbegin(); - i = c.rend(); + typedef typename Mutable_ForwardContainer::iterator iterator; + BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator)); + BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator)); + + reverse_iterator i = c.rbegin(); + i = c.rend(); } private: - ReversibleContainer c; + C c; }; - template - struct RandomAccessContainerConcept - : ReversibleContainerConcept + BOOST_concept(RandomAccessContainer,(C)) + : ReversibleContainer { - typedef typename RandomAccessContainer::size_type size_type; - typedef typename RandomAccessContainer::const_reference const_reference; + typedef typename C::size_type size_type; + typedef typename C::const_reference const_reference; - ~RandomAccessContainerConcept() + ~RandomAccessContainer() { BOOST_CONCEPT_ASSERT(( - RandomAccessIteratorConcept< - typename RandomAccessContainerConcept::const_iterator + RandomAccessIterator< + typename RandomAccessContainer::const_iterator >)); const_constraints(c); } private: - void const_constraints(const RandomAccessContainer& cc) + void const_constraints(const C& cc) { const_reference r = cc[n]; ignore_unused_variable_warning(r); } - RandomAccessContainer c; + C c; size_type n; }; - template - struct Mutable_RandomAccessContainerConcept - : Mutable_ReversibleContainerConcept - , RandomAccessContainerConcept + BOOST_concept(Mutable_RandomAccessContainer,(C)) + : Mutable_ReversibleContainer + , RandomAccessContainer { private: - typedef Mutable_RandomAccessContainerConcept self; + typedef Mutable_RandomAccessContainer self; public: - ~Mutable_RandomAccessContainerConcept() + ~Mutable_RandomAccessContainer() { - BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIteratorConcept)); - BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIteratorConcept)); + BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator)); + BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator)); typename self::reference r = c[i]; ignore_unused_variable_warning(r); } private: - typename Mutable_ReversibleContainerConcept::size_type i; - RandomAccessContainer c; + typename Mutable_ReversibleContainer::size_type i; + C c; }; // A Sequence is inherently mutable - template - struct SequenceConcept - : Mutable_ForwardContainerConcept + BOOST_concept(Sequence,(S)) + : Mutable_ForwardContainer // Matt Austern's book puts DefaultConstructible here, the C++ // standard places it in Container --JGS // ... so why aren't we following the standard? --DWA - , DefaultConstructibleConcept + , DefaultConstructible { - ~SequenceConcept() + ~Sequence() { - Sequence + S c(n), c2(n, t), c3(first, last); @@ -803,7 +764,7 @@ namespace boost c.erase(p); c.erase(p, q); - typename SequenceConcept::reference r = c.front(); + typename Sequence::reference r = c.front(); ignore_unused_variable_warning(c); ignore_unused_variable_warning(c2); @@ -812,64 +773,61 @@ namespace boost const_constraints(c); } private: - void const_constraints(const Sequence& c) { - typename SequenceConcept::const_reference r = c.front(); + void const_constraints(const S& c) { + typename Sequence::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; + typename S::value_type t; + typename S::size_type n; + typename S::value_type* first, *last; + typename S::iterator p, q; }; - template - struct FrontInsertionSequenceConcept - : SequenceConcept + BOOST_concept(FrontInsertionSequence,(S)) + : Sequence { - ~FrontInsertionSequenceConcept() + ~FrontInsertionSequence() { c.push_front(t); c.pop_front(); } private: - FrontInsertionSequence c; - typename FrontInsertionSequence::value_type t; + S c; + typename S::value_type t; }; - template - struct BackInsertionSequenceConcept - : SequenceConcept + BOOST_concept(BackInsertionSequence,(S)) + : Sequence { - ~BackInsertionSequenceConcept() + ~BackInsertionSequence() { c.push_back(t); c.pop_back(); - typename BackInsertionSequenceConcept::reference r = c.back(); + typename BackInsertionSequence::reference r = c.back(); ignore_unused_variable_warning(r); const_constraints(c); } private: - void const_constraints(const BackInsertionSequence& cc) { - typename BackInsertionSequenceConcept::const_reference + void const_constraints(const S& cc) { + typename BackInsertionSequence::const_reference r = cc.back(); ignore_unused_variable_warning(r); }; - BackInsertionSequence c; - typename BackInsertionSequence::value_type t; + S c; + typename S::value_type t; }; - template - struct AssociativeContainerConcept - : ForwardContainerConcept - , DefaultConstructibleConcept + BOOST_concept(AssociativeContainer,(C)) + : ForwardContainer + , DefaultConstructible { - 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; + 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; - ~AssociativeContainerConcept() + ~AssociativeContainer() { i = c.find(k); r = c.equal_range(k); @@ -877,38 +835,37 @@ namespace boost c.erase(i); c.erase(r.first, r.second); const_constraints(c); - BOOST_CONCEPT_ASSERT((BinaryPredicateConcept)); + BOOST_CONCEPT_ASSERT((BinaryPredicate)); - typedef typename AssociativeContainerConcept::value_type value_type_; - BOOST_CONCEPT_ASSERT((BinaryPredicateConcept)); + typedef typename AssociativeContainer::value_type value_type_; + BOOST_CONCEPT_ASSERT((BinaryPredicate)); } // Redundant with the base concept, but it helps below. - typedef typename AssociativeContainer::const_iterator const_iterator; + typedef typename C::const_iterator const_iterator; private: - void const_constraints(const AssociativeContainer& cc) + void const_constraints(const C& cc) { ci = cc.find(k); n = cc.count(k); cr = cc.equal_range(k); } - AssociativeContainer c; + C c; iterator i; std::pair r; const_iterator ci; std::pair cr; - typename AssociativeContainer::key_type k; - typename AssociativeContainer::size_type n; + typename C::key_type k; + typename C::size_type n; }; - template - struct UniqueAssociativeContainerConcept - : AssociativeContainerConcept + BOOST_concept(UniqueAssociativeContainer,(C)) + : AssociativeContainer { - ~UniqueAssociativeContainerConcept() + ~UniqueAssociativeContainer() { - UniqueAssociativeContainer c(first, last); + C c(first, last); pos_flag = c.insert(t); c.insert(first, last); @@ -916,18 +873,17 @@ namespace boost ignore_unused_variable_warning(c); } private: - std::pair pos_flag; - typename UniqueAssociativeContainer::value_type t; - typename UniqueAssociativeContainer::value_type* first, *last; + std::pair pos_flag; + typename C::value_type t; + typename C::value_type* first, *last; }; - template - struct MultipleAssociativeContainerConcept - : AssociativeContainerConcept + BOOST_concept(MultipleAssociativeContainer,(C)) + : AssociativeContainer { - ~MultipleAssociativeContainerConcept() + ~MultipleAssociativeContainer() { - MultipleAssociativeContainer c(first, last); + C c(first, last); pos = c.insert(t); c.insert(first, last); @@ -936,45 +892,42 @@ namespace boost ignore_unused_variable_warning(pos); } private: - typename MultipleAssociativeContainer::iterator pos; - typename MultipleAssociativeContainer::value_type t; - typename MultipleAssociativeContainer::value_type* first, *last; + typename C::iterator pos; + typename C::value_type t; + typename C::value_type* first, *last; }; - template - struct SimpleAssociativeContainerConcept - : AssociativeContainerConcept + BOOST_concept(SimpleAssociativeContainer,(C)) + : AssociativeContainer { - ~SimpleAssociativeContainerConcept() + ~SimpleAssociativeContainer() { - typedef typename SimpleAssociativeContainer::key_type key_type; - typedef typename SimpleAssociativeContainer::value_type value_type; + typedef typename C::key_type key_type; + typedef typename C::value_type value_type; BOOST_MPL_ASSERT((boost::is_same)); } }; - template - struct PairAssociativeContainerConcept - : AssociativeContainerConcept + BOOST_concept(PairAssociativeContainer,(C)) + : AssociativeContainer { - ~PairAssociativeContainerConcept() + ~PairAssociativeContainer() { - typedef typename SimpleAssociativeContainer::key_type key_type; - typedef typename SimpleAssociativeContainer::value_type value_type; - typedef typename SimpleAssociativeContainer::mapped_type mapped_type; + typedef typename C::key_type key_type; + typedef typename C::value_type value_type; + typedef typename C::mapped_type mapped_type; typedef std::pair required_value_type; BOOST_MPL_ASSERT((boost::is_same)); } }; - template - struct SortedAssociativeContainerConcept - : AssociativeContainerConcept - , ReversibleContainerConcept + BOOST_concept(SortedAssociativeContainer,(C)) + : AssociativeContainer + , ReversibleContainer { - ~SortedAssociativeContainerConcept() + ~SortedAssociativeContainer() { - SortedAssociativeContainer + C c(kc), c2(first, last), c3(first, last, kc); @@ -991,7 +944,7 @@ namespace boost const_constraints(c); } - void const_constraints(const SortedAssociativeContainer& c) + void const_constraints(const C& c) { kc = c.key_comp(); vc = c.value_comp(); @@ -1002,24 +955,26 @@ namespace boost } private: - 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; + 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 SortedAssociativeContainerConcept self; + typedef SortedAssociativeContainer self; iterator p; const_iterator cp; std::pair r; std::pair cr; - typename SortedAssociativeContainer::value_type* first, *last; + typename C::value_type* first, *last; }; // HashedAssociativeContainer } // namespace boost +# include + #endif // BOOST_CONCEPT_CHECKS_HPP diff --git a/stl_concept_check.cpp b/stl_concept_check.cpp index f84e220..8ec6f96 100644 --- a/stl_concept_check.cpp +++ b/stl_concept_check.cpp @@ -20,7 +20,7 @@ #include #include #include -#ifndef BOOST_NO_SLIST +#if 0 #include #endif @@ -43,27 +43,27 @@ main() typedef std::list List; // VC++ missing pointer and const_pointer typedefs - function_requires< Mutable_RandomAccessContainerConcept >(); - function_requires< BackInsertionSequenceConcept >(); + function_requires< Mutable_RandomAccessContainer >(); + function_requires< BackInsertionSequence >(); #if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS)) #if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS)) // old deque iterator missing n + iter operation - function_requires< Mutable_RandomAccessContainerConcept >(); + function_requires< Mutable_RandomAccessContainer >(); #endif // warnings about signed and unsigned in old deque version - function_requires< FrontInsertionSequenceConcept >(); - function_requires< BackInsertionSequenceConcept >(); + function_requires< FrontInsertionSequence >(); + function_requires< BackInsertionSequence >(); #endif // VC++ missing pointer and const_pointer typedefs - function_requires< Mutable_ReversibleContainerConcept >(); - function_requires< FrontInsertionSequenceConcept >(); - function_requires< BackInsertionSequenceConcept >(); + function_requires< Mutable_ReversibleContainer >(); + function_requires< FrontInsertionSequence >(); + function_requires< BackInsertionSequence >(); -#ifndef BOOST_NO_SLIST +#if 0 typedef BOOST_STD_EXTENSION_NAMESPACE::slist SList; - function_requires< FrontInsertionSequenceConcept >(); + function_requires< FrontInsertionSequence >(); #endif typedef std::set Set; @@ -71,21 +71,21 @@ main() typedef std::map Map; typedef std::multimap MultiMap; - function_requires< SortedAssociativeContainerConcept >(); - function_requires< SimpleAssociativeContainerConcept >(); - function_requires< UniqueAssociativeContainerConcept >(); + function_requires< SortedAssociativeContainer >(); + function_requires< SimpleAssociativeContainer >(); + function_requires< UniqueAssociativeContainer >(); - function_requires< SortedAssociativeContainerConcept >(); - function_requires< SimpleAssociativeContainerConcept >(); - function_requires< MultipleAssociativeContainerConcept >(); + function_requires< SortedAssociativeContainer >(); + function_requires< SimpleAssociativeContainer >(); + function_requires< MultipleAssociativeContainer >(); - function_requires< SortedAssociativeContainerConcept >(); - function_requires< UniqueAssociativeContainerConcept >(); - function_requires< PairAssociativeContainerConcept >(); + function_requires< SortedAssociativeContainer >(); + function_requires< UniqueAssociativeContainer >(); + function_requires< PairAssociativeContainer >(); - function_requires< SortedAssociativeContainerConcept >(); - function_requires< MultipleAssociativeContainerConcept >(); - function_requires< PairAssociativeContainerConcept >(); + function_requires< SortedAssociativeContainer >(); + function_requires< MultipleAssociativeContainer >(); + function_requires< PairAssociativeContainer >(); #endif return 0; diff --git a/stl_concept_covering.cpp b/stl_concept_covering.cpp index 5b05beb..338d23f 100644 --- a/stl_concept_covering.cpp +++ b/stl_concept_covering.cpp @@ -177,7 +177,7 @@ main() typedef equal_op_first_archetype<> Left; typedef input_iterator_archetype InIter; InIter in; - function_requires< InputIteratorConcept >(); + function_requires< InputIterator >(); equal_op_second_archetype<> value(dummy_cons); std::iterator_traits::difference_type n = std::count(in, in, value); From ba2a75c1f9013517ceedbd7f6913abd6e377b1c0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 1 May 2006 19:45:04 +0000 Subject: [PATCH 10/25] Added legibility. [SVN r33895] --- include/boost/concept/detail/concept_def.hpp | 28 ++++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/include/boost/concept/detail/concept_def.hpp b/include/boost/concept/detail/concept_def.hpp index 56ba817..c8949c2 100755 --- a/include/boost/concept/detail/concept_def.hpp +++ b/include/boost/concept/detail/concept_def.hpp @@ -3,9 +3,10 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP # define BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP -# include # include # include +# include +# include #endif // BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP // BOOST_concept(SomeName, (p1)(p2)...(pN)) @@ -14,16 +15,21 @@ // // Also defines an equivalent SomeNameConcept for backward compatibility. // Maybe in the next release we can kill off the "Concept" suffix for good. +# define BOOST_concept(name, params) \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name; /* forward decl */ \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct BOOST_PP_CAT(name,Concept) \ + : name< BOOST_PP_SEQ_ENUM(params) > \ + { \ + BOOST_PP_CAT(name,Concept)(); /* ctor needed to satisfy gcc-3.4.4 */ \ + }; \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name + +// Helper for BOOST_concept, above. # define BOOST_CONCEPT_typename(r, ignored, index, t) \ BOOST_PP_COMMA_IF(index) typename t -# define BOOST_concept(name, params) \ - template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename, ~, params) > \ - struct name; \ - template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename, ~, params) > \ - struct BOOST_PP_CAT(name,Concept) : name< BOOST_PP_SEQ_ENUM(params) > \ - { BOOST_PP_CAT(name,Concept)(); }; /* ctor needed to satisfy gcc-3.4.4 */ \ - template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename, ~, params) > \ - struct name - - From 4e524d6c6ac26454047d2b90cd1d5bfe7db3c4d2 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 1 May 2006 19:52:34 +0000 Subject: [PATCH 11/25] Workaround for GCC-2.96 [SVN r33896] --- include/boost/concept/assert.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/boost/concept/assert.hpp b/include/boost/concept/assert.hpp index 8d689ea..871660c 100755 --- a/include/boost/concept/assert.hpp +++ b/include/boost/concept/assert.hpp @@ -17,9 +17,13 @@ # if !defined(BOOST_NO_OLD_CONCEPT_SUPPORT) \ && !defined(BOOST_NO_SFINAE) \ - && !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4)) + \ + && !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4)) \ + && !(BOOST_WORKAROUND(__GNUC__, == 2) + +// Note: gcc-2.96 through 3.3.x have some SFINAE, but no ability to +// check for the presence of particularmember functions. -// Note: gcc-3.3.x had no member function pointer SFINAE # define BOOST_OLD_CONCEPT_SUPPORT # endif From 14450b3d5df6560d48b1c0eb968ac33093135974 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 1 May 2006 20:06:13 +0000 Subject: [PATCH 12/25] Added missing paren [SVN r33897] --- include/boost/concept/assert.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/concept/assert.hpp b/include/boost/concept/assert.hpp index 871660c..80eca81 100755 --- a/include/boost/concept/assert.hpp +++ b/include/boost/concept/assert.hpp @@ -19,7 +19,7 @@ && !defined(BOOST_NO_SFINAE) \ \ && !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4)) \ - && !(BOOST_WORKAROUND(__GNUC__, == 2) + && !(BOOST_WORKAROUND(__GNUC__, == 2)) // Note: gcc-2.96 through 3.3.x have some SFINAE, but no ability to // check for the presence of particularmember functions. From b087894c0842f5016e0e4b5902188af1a8ec9a55 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 8 May 2006 00:54:00 +0000 Subject: [PATCH 13/25] vc-7.1 workarounds [SVN r33961] --- include/boost/concept/detail/msvc.hpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/include/boost/concept/detail/msvc.hpp b/include/boost/concept/detail/msvc.hpp index 7165d44..3aadb79 100755 --- a/include/boost/concept/detail/msvc.hpp +++ b/include/boost/concept/detail/msvc.hpp @@ -27,11 +27,12 @@ struct check namespace detail { - // No need for a virtual function here, since evaluatiing + // No need for a virtual function here, since evaluating // not_satisfied below will have already instantiated the // constraints() member. struct constraint {}; } + template struct require : mpl::if_c< @@ -54,19 +55,22 @@ struct require // // The iterator library sees some really strange errors unless we -// use partial specialization to extract the model type with -// msvc-7.1 -// +// do things this way. +// template struct require - : require -{}; +{ + virtual void failed(Model*) + { + require(); + } +}; # define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ enum \ { \ BOOST_PP_CAT(boost_concept_check,__LINE__) = \ - sizeof(::boost::concept::require) \ + sizeof(::boost::concept::require) \ } # else // Not vc-7.1 From fb99b2546af04e907856205628b04a41d2379dde Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 15 May 2006 13:29:23 +0000 Subject: [PATCH 14/25] Minor cleanups [SVN r33967] --- include/boost/concept/where.hpp | 17 +++++++++++++++-- include/boost/concept_check.hpp | 1 - 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/boost/concept/where.hpp b/include/boost/concept/where.hpp index eec01b7..c91c1f9 100755 --- a/include/boost/concept/where.hpp +++ b/include/boost/concept/where.hpp @@ -10,8 +10,21 @@ namespace boost { +// Template for use in handwritten assertions +template +struct where_ : More +{ +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typedef typename More::type type; +# endif + BOOST_CONCEPT_ASSERT((Model)); +}; + +// Template for use by macros, where models must be wrapped in parens. +// This isn't in namespace detail to keep extra cruft out of resulting +// error messages. template -struct where : More +struct _where_ : More { # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) typedef typename More::type type; @@ -19,7 +32,7 @@ struct where : More BOOST_CONCEPT_ASSERT_FN(ModelFn); }; -#define BOOST_CONCEPT_WHERE_OPEN(r,data,t) ::boost::where #if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300) diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 3b43f2c..73058dc 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -336,7 +336,6 @@ namespace boost Func f; First first; Second second; - Return r; }; BOOST_concept(UnaryPredicate,(Func)(Arg)) From 178e7549ce46eca8b6299799da6825ea120ea078 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 2 Jun 2006 15:01:19 +0000 Subject: [PATCH 15/25] Work around GCC 3.3 bug [SVN r34134] --- include/boost/concept_check.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 73058dc..5b5c18f 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -126,6 +126,10 @@ namespace boost BOOST_concept(Assignable,(TT)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Assignable() { } +#endif + ~Assignable() { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator From b11b270a56db3966672454341ea9655de6335a6d Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 27 Jun 2006 15:01:14 +0000 Subject: [PATCH 16/25] Deal with GCC problems in updated concepts library [SVN r34418] --- include/boost/concept/detail/concept_def.hpp | 20 ++- include/boost/concept_check.hpp | 180 ++++++++++++++++++- 2 files changed, 191 insertions(+), 9 deletions(-) diff --git a/include/boost/concept/detail/concept_def.hpp b/include/boost/concept/detail/concept_def.hpp index c8949c2..79f628e 100755 --- a/include/boost/concept/detail/concept_def.hpp +++ b/include/boost/concept/detail/concept_def.hpp @@ -15,19 +15,35 @@ // // Also defines an equivalent SomeNameConcept for backward compatibility. // Maybe in the next release we can kill off the "Concept" suffix for good. +#if BOOST_WORKAROUND(__GNUC__, <= 3) # define BOOST_concept(name, params) \ template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ - struct name; /* forward decl */ \ + struct name; /* forward declaration */ \ \ template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ struct BOOST_PP_CAT(name,Concept) \ : name< BOOST_PP_SEQ_ENUM(params) > \ { \ - BOOST_PP_CAT(name,Concept)(); /* ctor needed to satisfy gcc-3.4.4 */ \ + /* at least 2.96 and 3.4.3 both need this */ \ + BOOST_PP_CAT(name,Concept)(); \ }; \ \ template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ struct name +#else +# define BOOST_concept(name, params) \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name; /* forward declaration */ \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct BOOST_PP_CAT(name,Concept) \ + : name< BOOST_PP_SEQ_ENUM(params) > \ + { \ + }; \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name +#endif // Helper for BOOST_concept, above. # define BOOST_CONCEPT_typename(r, ignored, index, t) \ diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 5b5c18f..5a127b8 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -60,6 +60,9 @@ namespace boost // BOOST_concept(Integer, (T)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Integer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Integer() { x.error_type_must_be_an_integer_type(); @@ -79,6 +82,9 @@ namespace boost // etc. BOOST_concept(SignedInteger,(T)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + SignedInteger(); // at least 2.96 and 3.4.3 both need this :( +#endif ~SignedInteger() { x.error_type_must_be_a_signed_integer_type(); } @@ -95,6 +101,9 @@ namespace boost #endif BOOST_concept(UnsignedInteger,(T)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + UnsignedInteger(); // at least 2.96 and 3.4.3 both need this :( +#endif ~UnsignedInteger() { x.error_type_must_be_an_unsigned_integer_type(); } @@ -118,6 +127,9 @@ namespace boost BOOST_concept(DefaultConstructible,(TT)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + DefaultConstructible(); // at least 2.96 and 3.4.3 both need this :( +#endif ~DefaultConstructible() { TT a; // require default constructor ignore_unused_variable_warning(a); @@ -127,7 +139,7 @@ namespace boost BOOST_concept(Assignable,(TT)) { #if BOOST_WORKAROUND(__GNUC__, <= 3) - Assignable() { } + Assignable(); // at least 2.96 and 3.4.3 both need this :( #endif ~Assignable() { @@ -148,6 +160,10 @@ namespace boost BOOST_concept(CopyConstructible,(TT)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + CopyConstructible(); // at least 2.96 and 3.4.3 both need this :( +#endif + ~CopyConstructible() { TT a(b); // require copy constructor TT* ptr = &a; // require address of operator @@ -167,6 +183,10 @@ namespace boost // The SGI STL version of Assignable requires copy constructor and operator= BOOST_concept(SGIAssignable,(TT)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + SGIAssignable(); // at least 2.96 and 3.4.3 both need this :( +#endif + ~SGIAssignable() { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL @@ -188,6 +208,9 @@ namespace boost BOOST_concept(Convertible,(X)(Y)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Convertible(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Convertible() { Y y = x; ignore_unused_variable_warning(y); @@ -213,6 +236,9 @@ namespace boost BOOST_concept(EqualityComparable,(TT)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + EqualityComparable(); // at least 2.96 and 3.4.3 both need this :( +#endif ~EqualityComparable() { require_boolean_expr(a == b); require_boolean_expr(a != b); @@ -223,6 +249,9 @@ namespace boost BOOST_concept(LessThanComparable,(TT)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + LessThanComparable(); // at least 2.96 and 3.4.3 both need this :( +#endif ~LessThanComparable() { require_boolean_expr(a < b); } @@ -233,6 +262,9 @@ namespace boost // This is equivalent to SGI STL's LessThanComparable. BOOST_concept(Comparable,(TT)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Comparable(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Comparable() { require_boolean_expr(a < b); require_boolean_expr(a > b); @@ -243,6 +275,18 @@ namespace boost TT a, b; }; +#if BOOST_WORKAROUND(__GNUC__, <= 3) +#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ + BOOST_concept(NAME, (First)(Second)) \ + { \ + NAME(); \ + ~NAME() { (void)constraints_(); } \ + private: \ + bool constraints_() { return a OP b; } \ + First a; \ + Second b; \ + } +#else #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (First)(Second)) \ { \ @@ -251,8 +295,21 @@ namespace boost bool constraints_() { return a OP b; } \ First a; \ Second b; \ - } + } +#endif +#if BOOST_WORKAROUND(__GNUC__, <= 3) +#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ + BOOST_concept(NAME, (Ret)(First)(Second)) \ + { \ + NAME(); \ + ~NAME() { (void)constraints_(); } \ + private: \ + Ret constraints_() { return a OP b; } \ + First a; \ + Second b; \ + } +#else #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (Ret)(First)(Second)) \ { \ @@ -261,7 +318,8 @@ namespace boost Ret constraints_() { return a OP b; } \ First a; \ Second b; \ - } + } +#endif BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp); @@ -281,6 +339,9 @@ namespace boost BOOST_concept(Generator,(Func)(Return)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Generator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Generator() { test(is_void()); } private: @@ -299,9 +360,11 @@ namespace boost Func f; }; - BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + UnaryFunction(); // at least 2.96 and 3.4.3 both need this :( +#endif ~UnaryFunction() { test(is_void()); } private: @@ -323,6 +386,9 @@ namespace boost BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + BinaryFunction(); // at least 2.96 and 3.4.3 both need this :( +#endif ~BinaryFunction() { test(is_void()); } private: void test(boost::mpl::false_) @@ -344,6 +410,9 @@ namespace boost BOOST_concept(UnaryPredicate,(Func)(Arg)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + UnaryPredicate(); // at least 2.96 and 3.4.3 both need this :( +#endif ~UnaryPredicate() { require_boolean_expr(f(arg)); // require operator() returning bool } @@ -354,6 +423,9 @@ namespace boost BOOST_concept(BinaryPredicate,(Func)(First)(Second)) { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( +#endif ~BinaryPredicate() { require_boolean_expr(f(a, b)); // require operator() returning bool } @@ -367,6 +439,9 @@ namespace boost BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) : BinaryPredicate { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Const_BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Const_BinaryPredicate() { const_constraints(f); } @@ -385,6 +460,9 @@ namespace boost { typedef typename Func::result_type result_type; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + AdaptableGenerator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~AdaptableGenerator() { BOOST_CONCEPT_ASSERT((Convertible)); @@ -397,6 +475,9 @@ namespace boost typedef typename Func::argument_type argument_type; typedef typename Func::result_type result_type; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + AdaptableUnaryFunction(); // at least 2.96 and 3.4.3 both need this :( +#endif ~AdaptableUnaryFunction() { BOOST_CONCEPT_ASSERT((Convertible)); @@ -416,6 +497,9 @@ namespace boost typedef typename Func::second_argument_type second_argument_type; typedef typename Func::result_type result_type; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + AdaptableBinaryFunction(); // at least 2.96 and 3.4.3 both need this :( +#endif ~AdaptableBinaryFunction() { BOOST_CONCEPT_ASSERT((Convertible)); @@ -427,12 +511,20 @@ namespace boost BOOST_concept(AdaptablePredicate,(Func)(Arg)) : UnaryPredicate , AdaptableUnaryFunction - {}; + { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + AdaptablePredicate(); // at least 2.96 and 3.4.3 both need this :( +#endif + }; BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second)) : BinaryPredicate , AdaptableBinaryFunction - {}; + { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + AdaptableBinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( +#endif + }; //=========================================================================== // Iterator Concepts @@ -447,6 +539,9 @@ namespace boost typedef typename boost::detail::iterator_traits::pointer pointer; typedef typename boost::detail::iterator_traits::iterator_category iterator_category; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + InputIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~InputIterator() { BOOST_CONCEPT_ASSERT((SignedInteger)); @@ -464,6 +559,9 @@ namespace boost BOOST_concept(OutputIterator,(TT)(ValueT)) : Assignable { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + OutputIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~OutputIterator() { ++i; // require preincrement operator @@ -478,6 +576,9 @@ namespace boost BOOST_concept(ForwardIterator,(TT)) : InputIterator { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + ForwardIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~ForwardIterator() { BOOST_CONCEPT_ASSERT((Convertible< @@ -496,6 +597,9 @@ namespace boost BOOST_concept(Mutable_ForwardIterator,(TT)) : ForwardIterator { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Mutable_ForwardIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Mutable_ForwardIterator() { *i++ = *i; // require postincrement and assignment } @@ -506,6 +610,9 @@ namespace boost BOOST_concept(BidirectionalIterator,(TT)) : ForwardIterator { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~BidirectionalIterator() { BOOST_CONCEPT_ASSERT((Convertible< @@ -524,6 +631,9 @@ namespace boost : BidirectionalIterator , Mutable_ForwardIterator { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Mutable_BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Mutable_BidirectionalIterator() { *i-- = *i; // require postdecrement and assignment @@ -532,11 +642,13 @@ namespace boost TT i; }; - BOOST_concept(RandomAccessIterator,(TT)) : BidirectionalIterator , Comparable { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~RandomAccessIterator() { BOOST_CONCEPT_ASSERT((Convertible< @@ -562,6 +674,9 @@ namespace boost : RandomAccessIterator , Mutable_BidirectionalIterator { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Mutable_RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Mutable_RandomAccessIterator() { i[n] = *i; // require element access and assignment @@ -584,6 +699,9 @@ namespace boost typedef typename C::const_pointer const_pointer; typedef typename C::const_iterator const_iterator; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Container(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Container() { BOOST_CONCEPT_ASSERT((InputIterator)); @@ -611,6 +729,9 @@ namespace boost typedef typename C::iterator iterator; typedef typename C::pointer pointer; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Mutable_Container(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Mutable_Container() { BOOST_CONCEPT_ASSERT(( @@ -631,6 +752,9 @@ namespace boost BOOST_concept(ForwardContainer,(C)) : Container { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + ForwardContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~ForwardContainer() { BOOST_CONCEPT_ASSERT(( @@ -644,6 +768,9 @@ namespace boost : ForwardContainer , Mutable_Container { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Mutable_ForwardContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Mutable_ForwardContainer() { BOOST_CONCEPT_ASSERT(( @@ -660,6 +787,9 @@ namespace boost C::const_reverse_iterator const_reverse_iterator; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~ReversibleContainer() { BOOST_CONCEPT_ASSERT(( @@ -685,6 +815,9 @@ namespace boost { typedef typename C::reverse_iterator reverse_iterator; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Mutable_ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Mutable_ReversibleContainer() { typedef typename Mutable_ForwardContainer::iterator iterator; @@ -704,6 +837,9 @@ namespace boost typedef typename C::size_type size_type; typedef typename C::const_reference const_reference; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~RandomAccessContainer() { BOOST_CONCEPT_ASSERT(( @@ -731,6 +867,9 @@ namespace boost private: typedef Mutable_RandomAccessContainer self; public: +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Mutable_RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Mutable_RandomAccessContainer() { BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator)); @@ -753,6 +892,9 @@ namespace boost // ... so why aren't we following the standard? --DWA , DefaultConstructible { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + Sequence(); // at least 2.96 and 3.4.3 both need this :( +#endif ~Sequence() { S @@ -790,6 +932,9 @@ namespace boost BOOST_concept(FrontInsertionSequence,(S)) : Sequence { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + FrontInsertionSequence(); // at least 2.96 and 3.4.3 both need this :( +#endif ~FrontInsertionSequence() { c.push_front(t); @@ -803,6 +948,9 @@ namespace boost BOOST_concept(BackInsertionSequence,(S)) : Sequence { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + BackInsertionSequence(); // at least 2.96 and 3.4.3 both need this :( +#endif ~BackInsertionSequence() { c.push_back(t); @@ -830,6 +978,9 @@ namespace boost typedef typename C::value_compare value_compare; typedef typename C::iterator iterator; +#if BOOST_WORKAROUND(__GNUC__, <= 3) + AssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~AssociativeContainer() { i = c.find(k); @@ -866,6 +1017,9 @@ namespace boost BOOST_concept(UniqueAssociativeContainer,(C)) : AssociativeContainer { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + UniqueAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~UniqueAssociativeContainer() { C c(first, last); @@ -884,6 +1038,9 @@ namespace boost BOOST_concept(MultipleAssociativeContainer,(C)) : AssociativeContainer { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + MultipleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~MultipleAssociativeContainer() { C c(first, last); @@ -903,6 +1060,9 @@ namespace boost BOOST_concept(SimpleAssociativeContainer,(C)) : AssociativeContainer { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + SimpleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~SimpleAssociativeContainer() { typedef typename C::key_type key_type; @@ -914,6 +1074,9 @@ namespace boost BOOST_concept(PairAssociativeContainer,(C)) : AssociativeContainer { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + PairAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~PairAssociativeContainer() { typedef typename C::key_type key_type; @@ -928,6 +1091,9 @@ namespace boost : AssociativeContainer , ReversibleContainer { +#if BOOST_WORKAROUND(__GNUC__, <= 3) + SortedAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( +#endif ~SortedAssociativeContainer() { C From 6b4d01994b6ccf3c1d92a32b6ce7cf1f7bf5588e Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 11 Sep 2006 22:08:18 +0000 Subject: [PATCH 17/25] add missing license/copyright info [SVN r35068] --- Jamfile | 3 +++ Jamfile.v2 | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Jamfile b/Jamfile index e16f2a0..4cf9462 100644 --- a/Jamfile +++ b/Jamfile @@ -1,3 +1,6 @@ +# Copyright David Abrahams, Jeremy Siek 2006. 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) subproject libs/concept_check ; import testing ; diff --git a/Jamfile.v2 b/Jamfile.v2 index 251542f..18e51ef 100644 --- a/Jamfile.v2 +++ b/Jamfile.v2 @@ -1,4 +1,7 @@ - +# Copyright David Abrahams, Jeremy Siek, Vladimir Prus +# 2006. 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 ; test-suite concept_check From ac6415fac2eab9c61659fb3962a00b0fa0ff9c47 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 19 Sep 2006 13:37:20 +0000 Subject: [PATCH 18/25] Added BOOST_CONCEPT_USAGE for defining usage requirements: Using this macro is better than simply defining a destructor because usage patterns will be tested whenever associated types are accessed. [SVN r35198] --- Jamfile | 1 + Jamfile.v2 | 1 + include/boost/concept/usage.hpp | 32 +++++++++++++++++++++++ include/boost/concept_check.hpp | 46 +++++++++++++++++---------------- usage_fail.cpp | 22 ++++++++++++++++ 5 files changed, 80 insertions(+), 22 deletions(-) create mode 100755 include/boost/concept/usage.hpp create mode 100755 usage_fail.cpp diff --git a/Jamfile b/Jamfile index 4cf9462..1647aa6 100644 --- a/Jamfile +++ b/Jamfile @@ -15,6 +15,7 @@ test-suite concept_check [ run where.cpp ] [ compile-fail where_fail.cpp ] + [ compile-fail usage_fail.cpp ] # Backward compatibility tests [ run old_concept_pass.cpp ] diff --git a/Jamfile.v2 b/Jamfile.v2 index 18e51ef..7b7c833 100644 --- a/Jamfile.v2 +++ b/Jamfile.v2 @@ -14,6 +14,7 @@ test-suite concept_check [ run where.cpp ] [ compile-fail where_fail.cpp ] + [ compile-fail usage_fail.cpp ] # Backward compatibility tests [ run old_concept_pass.cpp ] diff --git a/include/boost/concept/usage.hpp b/include/boost/concept/usage.hpp new file mode 100755 index 0000000..399bd4c --- /dev/null +++ b/include/boost/concept/usage.hpp @@ -0,0 +1,32 @@ +// Copyright David Abrahams 2006. 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) +#ifndef BOOST_CONCEPT_USAGE_DWA2006919_HPP +# define BOOST_CONCEPT_USAGE_DWA2006919_HPP + +# include +# include + +namespace boost { namespace concept { + +# if BOOST_WORKAROUND(__GNUC__, == 2) + +# define BOOST_CONCEPT_USAGE(model) ~model() + +# else + +template +struct usage_requirements +{ + ~usage_requirements() { ((Model*)0)->~Model(); } +}; + +# define BOOST_CONCEPT_USAGE(model) \ + BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements)); \ + ~model() + +# endif + +}} // namespace boost::concept + +#endif // BOOST_CONCEPT_USAGE_DWA2006919_HPP diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 5a127b8..43db342 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -23,9 +23,11 @@ # include # include # include +# include # include # include +# include # include namespace boost @@ -63,7 +65,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Integer(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Integer() + BOOST_CONCEPT_USAGE(Integer) { x.error_type_must_be_an_integer_type(); } @@ -85,7 +87,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) SignedInteger(); // at least 2.96 and 3.4.3 both need this :( #endif - ~SignedInteger() { + BOOST_CONCEPT_USAGE(SignedInteger) { x.error_type_must_be_a_signed_integer_type(); } private: @@ -104,7 +106,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) UnsignedInteger(); // at least 2.96 and 3.4.3 both need this :( #endif - ~UnsignedInteger() { + BOOST_CONCEPT_USAGE(UnsignedInteger) { x.error_type_must_be_an_unsigned_integer_type(); } private: @@ -130,7 +132,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) DefaultConstructible(); // at least 2.96 and 3.4.3 both need this :( #endif - ~DefaultConstructible() { + BOOST_CONCEPT_USAGE(DefaultConstructible) { TT a; // require default constructor ignore_unused_variable_warning(a); } @@ -142,7 +144,7 @@ namespace boost Assignable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Assignable() { + BOOST_CONCEPT_USAGE(Assignable) { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator #endif @@ -164,7 +166,7 @@ namespace boost CopyConstructible(); // at least 2.96 and 3.4.3 both need this :( #endif - ~CopyConstructible() { + BOOST_CONCEPT_USAGE(CopyConstructible) { TT a(b); // require copy constructor TT* ptr = &a; // require address of operator const_constraints(a); @@ -187,7 +189,7 @@ namespace boost SGIAssignable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~SGIAssignable() { + BOOST_CONCEPT_USAGE(SGIAssignable) { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL a = a; // require assignment operator @@ -211,7 +213,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Convertible(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Convertible() { + BOOST_CONCEPT_USAGE(Convertible) { Y y = x; ignore_unused_variable_warning(y); } @@ -239,7 +241,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) EqualityComparable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~EqualityComparable() { + BOOST_CONCEPT_USAGE(EqualityComparable) { require_boolean_expr(a == b); require_boolean_expr(a != b); } @@ -252,7 +254,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) LessThanComparable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~LessThanComparable() { + BOOST_CONCEPT_USAGE(LessThanComparable) { require_boolean_expr(a < b); } private: @@ -265,7 +267,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Comparable(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Comparable() { + BOOST_CONCEPT_USAGE(Comparable) { require_boolean_expr(a < b); require_boolean_expr(a > b); require_boolean_expr(a <= b); @@ -280,7 +282,7 @@ namespace boost BOOST_concept(NAME, (First)(Second)) \ { \ NAME(); \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ bool constraints_() { return a OP b; } \ First a; \ @@ -290,7 +292,7 @@ namespace boost #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (First)(Second)) \ { \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ bool constraints_() { return a OP b; } \ First a; \ @@ -303,7 +305,7 @@ namespace boost BOOST_concept(NAME, (Ret)(First)(Second)) \ { \ NAME(); \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ Ret constraints_() { return a OP b; } \ First a; \ @@ -313,7 +315,7 @@ namespace boost #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (Ret)(First)(Second)) \ { \ - ~NAME() { (void)constraints_(); } \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ private: \ Ret constraints_() { return a OP b; } \ First a; \ @@ -342,7 +344,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Generator(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Generator() { test(is_void()); } + BOOST_CONCEPT_USAGE(Generator) { test(is_void()); } private: void test(boost::mpl::false_) @@ -365,7 +367,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) UnaryFunction(); // at least 2.96 and 3.4.3 both need this :( #endif - ~UnaryFunction() { test(is_void()); } + BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void()); } private: void test(boost::mpl::false_) @@ -389,7 +391,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) BinaryFunction(); // at least 2.96 and 3.4.3 both need this :( #endif - ~BinaryFunction() { test(is_void()); } + BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void()); } private: void test(boost::mpl::false_) { @@ -413,7 +415,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) UnaryPredicate(); // at least 2.96 and 3.4.3 both need this :( #endif - ~UnaryPredicate() { + BOOST_CONCEPT_USAGE(UnaryPredicate) { require_boolean_expr(f(arg)); // require operator() returning bool } private: @@ -426,7 +428,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( #endif - ~BinaryPredicate() { + BOOST_CONCEPT_USAGE(BinaryPredicate) { require_boolean_expr(f(a, b)); // require operator() returning bool } private: @@ -442,7 +444,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) Const_BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( #endif - ~Const_BinaryPredicate() { + BOOST_CONCEPT_USAGE(Const_BinaryPredicate) { const_constraints(f); } private: @@ -463,7 +465,7 @@ namespace boost #if BOOST_WORKAROUND(__GNUC__, <= 3) AdaptableGenerator(); // at least 2.96 and 3.4.3 both need this :( #endif - ~AdaptableGenerator() + BOOST_CONCEPT_USAGE(AdaptableGenerator) { BOOST_CONCEPT_ASSERT((Convertible)); } diff --git a/usage_fail.cpp b/usage_fail.cpp new file mode 100755 index 0000000..29796b9 --- /dev/null +++ b/usage_fail.cpp @@ -0,0 +1,22 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +template +struct StringInitializable +{ + typedef int associated; + BOOST_CONCEPT_USAGE(StringInitializable) + { + T x = "foo"; + } +}; + +// Test that accessing an associated type will actually exercise usage +// requirements +typedef StringInitializable::associated tee; + + + From c1709f67948127804a2a5281aac3b874f23ddf0e Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 7 Nov 2006 19:11:57 +0000 Subject: [PATCH 19/25] Add copyright, license [SVN r35905] --- index.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index cc13c7a..36fea49 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,10 @@ Automatic redirection failed, please go to -concept_check.htm. +concept_check.htm
    +

    Copyright Beman Dawes, 2001

    +

    Distributed under the Boost Software License, Version 1.0. (See accompanying +file LICENSE_1_0.txt or copy +at www.boost.org/LICENSE_1_0.txt)

    \ No newline at end of file From 6f04bb500424e9421d4b90711018f1d22e742fa6 Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Wed, 8 Aug 2007 19:02:26 +0000 Subject: [PATCH 20/25] Remove V1 Jamfiles [SVN r38516] --- Jamfile | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 Jamfile diff --git a/Jamfile b/Jamfile deleted file mode 100644 index 1647aa6..0000000 --- a/Jamfile +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright David Abrahams, Jeremy Siek 2006. 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) -subproject libs/concept_check ; - -import testing ; - -test-suite concept_check - : [ run stl_concept_covering.cpp ] - [ run stl_concept_check.cpp ] - [ run concept_check_test.cpp ] - [ run class_concept_check_test.cpp ] - [ compile-fail concept_check_fail_expected.cpp ] - [ compile-fail class_concept_fail_expected.cpp ] - - [ run where.cpp ] - [ compile-fail where_fail.cpp ] - [ compile-fail usage_fail.cpp ] - - # Backward compatibility tests - [ run old_concept_pass.cpp ] - [ compile-fail function_requires_fail.cpp ] - [ compile-fail old_concept_function_fail.cpp ] - [ compile-fail old_concept_class_fail.cpp ] - ; - From 9ef681483ea9adddaf63017dbe2343521646b986 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 13 Sep 2007 18:50:50 +0000 Subject: [PATCH 21/25] Work around bugs in Sun Studio 11 [SVN r39243] --- include/boost/concept/detail/has_constraints.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/boost/concept/detail/has_constraints.hpp b/include/boost/concept/detail/has_constraints.hpp index 7ffbb24..3112b55 100755 --- a/include/boost/concept/detail/has_constraints.hpp +++ b/include/boost/concept/detail/has_constraints.hpp @@ -5,7 +5,7 @@ # define BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP # include - +# include namespace boost { namespace concept { namespace detail @@ -19,9 +19,17 @@ namespace detail template struct wrap_constraints {}; +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) + // Work around the following bogus error in Sun Studio 11, by + // turning off the has_constraints function entirely: + // Error: complex expression not allowed in dependent template + // argument expression + inline no has_constraints_(...); +#else template inline yes has_constraints_(Model*, wrap_constraints* = 0); inline no has_constraints_(...); +#endif } // This would be called "detail::has_constraints," but it has a strong From 2134db932478980bbf70bcf6aeeb2d9e370d86e4 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 17 Sep 2007 18:33:20 +0000 Subject: [PATCH 22/25] Support Win64 [SVN r39353] --- include/boost/concept_check.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 43db342..69e5f9c 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -83,6 +83,11 @@ namespace boost template <> struct Integer {}; // etc. +#ifdef _WIN64 + template <> struct Integer<__int64> {}; + template <> struct Integer {}; +#endif + BOOST_concept(SignedInteger,(T)) { #if BOOST_WORKAROUND(__GNUC__, <= 3) SignedInteger(); // at least 2.96 and 3.4.3 both need this :( @@ -101,6 +106,9 @@ namespace boost template <> struct SignedInteger< ::boost::long_long_type> {}; // etc. #endif +#ifdef _WIN64 + template <> struct SignedInteger<__int64> {}; +#endif BOOST_concept(UnsignedInteger,(T)) { #if BOOST_WORKAROUND(__GNUC__, <= 3) @@ -121,6 +129,9 @@ namespace boost template <> struct UnsignedInteger< ::boost::ulong_long_type> {}; // etc. #endif +#ifdef _WIN64 + template <> struct UnsignedInteger {}; +#endif // etc. From 6ed3c013bb29bb5d6fd9323b77b38cd79cc1704c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 18 Sep 2007 12:09:53 +0000 Subject: [PATCH 23/25] Second attempt at fixing usage of 64-bit integer type [SVN r39363] --- include/boost/concept_check.hpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 69e5f9c..555f2b4 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -81,12 +81,13 @@ namespace boost template <> struct Integer {}; template <> struct Integer {}; template <> struct Integer {}; - // etc. - -#ifdef _WIN64 +# 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 {}; -#endif +# endif BOOST_concept(SignedInteger,(T)) { #if BOOST_WORKAROUND(__GNUC__, <= 3) @@ -104,11 +105,9 @@ namespace boost template <> struct SignedInteger {}; # if defined(BOOST_HAS_LONG_LONG) template <> struct SignedInteger< ::boost::long_long_type> {}; - // etc. -#endif -#ifdef _WIN64 +# elif defined(BOOST_HAS_MS_INT64) template <> struct SignedInteger<__int64> {}; -#endif +# endif BOOST_concept(UnsignedInteger,(T)) { #if BOOST_WORKAROUND(__GNUC__, <= 3) @@ -127,13 +126,9 @@ namespace boost template <> struct UnsignedInteger {}; # if defined(BOOST_HAS_LONG_LONG) template <> struct UnsignedInteger< ::boost::ulong_long_type> {}; - // etc. -#endif -#ifdef _WIN64 +# elif defined(BOOST_HAS_MS_INT64) template <> struct UnsignedInteger {}; -#endif - - // etc. +# endif //=========================================================================== // Basic Concepts From 7dd50ca8f298ce8a86dd1c6a0ca3d5ea6670e6ba Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Nov 2007 03:54:19 +0000 Subject: [PATCH 24/25] Updated Concept Check library documentation. Changed BOOST_CONCEPT_WHERE to BOOST_CONCEPT_REQUIRES to be more consistent with the current C++0x proposal, which now uses a "requires" keyword in lieu of "where." Factored GCC workarounds into the BOOST_CONCEPT_USAGE macro. [SVN r40769] --- bad_error_eg.cpp | 19 +- concept_check.htm | 536 ++++++++++++++--------------- concept_covering.htm | 225 +++++++------ creating_concepts.htm | 237 +++++++------ fake_sort.hpp | 2 +- implementation.htm | 225 ++++++------- include/boost/concept/usage.hpp | 17 +- include/boost/concept/where.hpp | 49 +-- include/boost/concept_check.hpp | 223 ++----------- prog_with_concepts.htm | 164 +++++---- reference.htm | 573 ++++++++++++++++++-------------- using_concept_check.htm | 359 +++++++++----------- 12 files changed, 1293 insertions(+), 1336 deletions(-) diff --git a/bad_error_eg.cpp b/bad_error_eg.cpp index 644ac4c..5f8d892 100644 --- a/bad_error_eg.cpp +++ b/bad_error_eg.cpp @@ -1,13 +1,14 @@ +#include +#include +#include "algorithm" + +int main() +{ + std::vector > v; + std_::stable_sort(v.begin(), v.end()); +} + // (C) Copyright Jeremy Siek 2000. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -int main() { - std::list v; - std::stable_sort(v.begin(), v.end()); - return 0; -} diff --git a/concept_check.htm b/concept_check.htm index 194b0c2..0f70167 100644 --- a/concept_check.htm +++ b/concept_check.htm @@ -1,312 +1,330 @@ - - - -Concept Check Library + + + + + + + + + + + + + Concept Check Library + - -C++ Boost + + C++ Boost
    -
    +

    The Boost Concept Check Library (BCCL)

    -

    The Boost Concept Check Library (BCCL)

    +
    + The Concept Check library allows one to add explicit statement and + checking of concepts in the style + of the proposed + C++ language extension. +
    -

    - -header -boost/concept_check.hpp -
    and -boost/concept_archetype.hpp -

    +

    Synopsis

    -

    -Generic programming in C++ is characterized by the use of template -parameters to represent abstract data types (or ``concepts''). -However, the C++ language itself does not provide a mechanism for the -writer of a class or function template to explicitly state what -concept the user-supplied template argument should model (or conform -to). The common practice is to name the template parameter after the -required concept as a hint to the user and to state the concept -requirements in the documentation. However, often times the -requirements are vague, incorrect, or nonexistent, which is quite a -problem for the user, since he or she will not know exactly what kind -of input is expected by the template. Furthermore, the following -problems occur: +

    Generic programming in C++ is characterized by the use of template + parameters to represent abstract data types (or “concepts”). However, the + C++ language itself does not provide a mechanism for the writer of a class + or function template to explicitly state the concept that the user-supplied + template argument should model (or conform to). Template parameters are + commonly named after the concept they're required to model as a hint to the + user, and to make the concept requirements explicit in code. However, the + compiler doesn't treat these special names specially: a parameter named + RandomAccessIterator is no different to the compiler than one + named T. Furthermore,

    -
      -
    • Compiler error messages resulting from incorrect template - arguments can be particularly difficult to decipher. Often times - the error does not point to the location of the template - call-site, but instead exposes the internals of the template, which - the user should never have to see.
    • +
        +
      • Compiler error messages resulting from incorrect template arguments + can be particularly difficult to decipher. Often times the error does not + point to the location of the template call-site, but instead exposes the + internals of the template, which the user should never have to see.
      • -
      • The documented concept requirements may not fully cover - the template, meaning the user could get a compiler error even - though the supplied template arguments meet the documented - requirements.
      • +
      • Without checking from the compiler, the documented requirements are + oftentimes vague, incorrect, or nonexistent, so a user cannot know + exactly what kind of arguments are expected.
      • -
      • The documented concept requirements may be too stringent, - requiring more than is really needed by the template.
      • +
      • The documented concept requirements may not fully cover the + needs of the actual template, meaning the user could get a compiler error + even though the supplied template arguments meet the documented + requirements.
      • -
      • The requirements are not explicitly stated in the code, which - makes the code harder to understand. Also, the code may - get out-of-sync with the documented requirements.
      • -
      +
    • The documented concept requirements may be too stringent, requiring + more than is really needed by the template.
    • -The Boost Concept Checking Library provides: +
    • Concept names in code may drift out-of-sync with the documented + requirements.
    • +

    The Boost Concept Checking Library provides: -

      -
    • A mechanism for inserting compile-time checks of template - parameters.
    • +
        +
      • A mechanism for inserting compile-time checks on template parameters + at their point of use.
      • -
      • A framework for specifying concept requirements though concept - checking classes.
      • +
      • A framework for specifying concept requirements though concept + checking classes.
      • -
      • A mechanism for verifying that concept requirements cover the template.
      • +
      • A mechanism for verifying that concept requirements cover the + template.
      • -
      • A suite of concept checking classes and archetype classes that - match the concept requirements in the C++ Standard Library.
      • -
      +
    • A suite of concept checking classes and archetype classes that match + the concept requirements in the C++ Standard Library.
    • -The mechanisms use standard C++ and introduce no run-time -overhead. The main cost of using the mechanism is in compile-time. +
    • An alternative to the use of traits classes for accessing associated + types that mirrors the syntax proposed for the next C++ standard.
    • +

    The mechanisms use standard C++ and introduce no run-time overhead. + The main cost of using the mechanism is in compile-time.

    -

    -Any programmer writing class or function templates ought to make -concept checking a normal part of their code writing routine. A -concept check should be inserted for each template parameter in a -component's public interface. If the concept is one of the ones from -the Standard Library, then simply use the matching concept checking -class in the BCCL. If not, then write a new concept checking class - -after all, they are typically only a few lines long. For new concepts, -a matching archetype class should also be created, which is a minimal -skeleton-implementation of the concept +

    Every programmer writing class or function templates ought to + make concept checking a normal part of their code writing routine. + A concept check should be inserted for each template parameter in a + component's public interface. If the concept is one of the ones from the + Standard Library, then simply use the matching concept checking class in + the BCCL. If not, then write a new concept checking class - after all, they + are typically only a few lines long. For new concepts, a matching archetype + class should also be created, which is a minimal skeleton-implementation of + the concept

    -

    -The documentation is organized into the following sections. +

    The documentation is organized into the following sections.

    -
      -
    1. Introduction
    2. -
    3. Motivating Example
    4. -
    5. History
    6. -
    7. Publications
    8. -
    9. Acknowledgements
    10. -
    11. Using Concept Checks
    12. -
    13. Creating Concept Checking Classes
    14. -
    15. Concept Covering and Archetypes
    16. -
    17. Programming With Concepts
    18. -
    19. Implementation
    20. -
    21. Reference
    22. -
    +
      +
    1. Introduction
    2. -

      -Jeremy Siek contributed -this library. Beman Dawes -managed the formal review. +

    3. Motivating Example
    4. -

      Introduction

      - -A concept is a set of requirements (valid expressions, -associated types, semantic invariants, complexity guarantees, etc.) -that a type must fulfill to be correctly used as arguments in a call -to a generic algorithm. In C++, concepts are represented by formal -template parameters to function templates (generic algorithms). -However, C++ has no explicit mechanism for representing concepts --- -template parameters are merely placeholders. By convention, these -parameters are given names corresponding to the concept that is -required, but a C++ compiler does not enforce compliance to the -concept when the template parameter is bound to an actual type. +
    5. History
    6. -

      -Naturally, if a generic algorithm is invoked with a type that does not -fulfill at least the syntactic requirements of the concept, a -compile-time error will occur. However, this error will not per - se reflect the fact that the type did not meet all of the -requirements of the concept. Rather, the error may occur deep inside -the instantiation hierarchy at the point where an expression is not -valid for the type, or where a presumed associated type is not -available. The resulting error messages are largely uninformative and -basically impenetrable. +

    7. Publications
    8. -

      -What is required is a mechanism for enforcing ``concept safety'' at -(or close to) the point of instantiation. The Boost Concept Checking -Library uses some standard C++ constructs to enforce early concept -compliance and that provides more informative error messages upon -non-compliance. +

    9. Acknowledgements
    10. -

      -Note that this technique only addresses the syntactic -requirements of concepts (the valid expressions and associated types). -We do not address the semantic invariants or complexity guarantees, -which are also part of concept requirements.. +

    11. Using Concept Checks
    12. -

      Motivating Example

      +
    13. Creating Concept Checking + Classes
    14. -We present a simple example to illustrate incorrect usage of a -template library and the resulting error messages. In the code below, -the generic std::stable_sort() algorithm from the Standard -Template Library (STL)[3, 4,5] is applied to -a linked list. +
    15. Concept Covering and + Archetypes
    16. -
      +    
    17. Programming With Concepts
    18. + +
    19. Implementation
    20. + +
    21. Reference
    22. +
    + +

    Jeremy Siek contributed this + library. Beman Dawes managed + the formal review. Dave + Abrahams contributed a rewrite that updated syntax to be more + compatible with proposed syntax for concept support the C++ core + language.

    + +

    Introduction

    A + concept is a set of requirements (valid expressions, associated + types, semantic invariants, complexity guarantees, etc.) that a type must + fulfill to be correctly used as arguments in a call to a generic algorithm. + In C++, concepts are represented by formal template parameters to function + templates (generic algorithms). However, C++ has no explicit mechanism for + representing concepts—template parameters are merely placeholders. By + convention, these parameters are given names corresponding to the concept + that is required, but a C++ compiler does not enforce compliance to the + concept when the template parameter is bound to an actual type. + +

    Naturally, if a generic algorithm is invoked with a type that does not + fulfill at least the syntactic requirements of the concept, a compile-time + error will occur. However, this error will not per se reflect the + fact that the type did not meet all of the requirements of the concept. + Rather, the error may occur deep inside the instantiation hierarchy at the + point where an expression is not valid for the type, or where a presumed + associated type is not available. The resulting error messages are largely + uninformative and basically impenetrable.

    + +

    What is required is a mechanism for enforcing + “concept safety” at (or close to) the point + of instantiation. The Boost Concept Checking Library uses some standard C++ + constructs to enforce early concept compliance and that provides more + informative error messages upon non-compliance.

    + +

    Note that this technique only addresses the syntactic requirements of + concepts (the valid expressions and associated types). We do not address + the semantic invariants or complexity guarantees, which are also part of + concept requirements..

    + +

    Motivating + Example

    + +

    We present a simple example to illustrate incorrect usage of a template + library and the resulting error messages. In the code below, the generic + std::stable_sort() algorithm from the Standard Template Library + (STL)[3, 4,5] is applied to a linked + list.

    +
       bad_error_eg.cpp:
    -   1  #include <list>
    -   2  #include <algorithm>
    -   3
    -   4  int main(int, char*[]) {
    -   5    std::list<int> v;
    -   6    std::stable_sort(v.begin(), v.end());
    -   7    return 0;
    -   8  }
    +1 #include <vector>
    +2 #include <complex>
    +3 #include <algorithm>
    +4 
    +5 int main()
    +6 {
    +7     std::vector<std::complex<float> > v;
    +8     std::stable_sort(v.begin(), v.end());
    +9 }
     
    -Here, the -std::stable_sort() algorithm is prototyped as follows: -
    +  

    Here, the std::stable_sort() algorithm is prototyped as + follows:

    +
       template <class RandomAccessIterator>
       void stable_sort(RandomAccessIterator first, RandomAccessIterator last);
     
    -Attempting to compile this code with Gnu C++ produces the following -compiler error. The output from other compilers is listed in the -Appendix. - -
    -stl_algo.h: In function `void __merge_sort_loop<_List_iterator
    -  <int,int &,int *>, int *, int>(_List_iterator<int,int &,int *>,
    -  _List_iterator<int,int &,int *>, int *, int)':
    -stl_algo.h:1448:   instantiated from `__merge_sort_with_buffer
    -  <_List_iterator<int,int &,int *>, int *, int>(
    -   _List_iterator<int,int &,int *>, _List_iterator<int,int &,int *>,
    -   int *, int *)'
    -stl_algo.h:1485:   instantiated from `__stable_sort_adaptive<
    -  _List_iterator<int,int &,int *>, int *, int>(_List_iterator
    -  <int,int &,int *>, _List_iterator<int,int &,int *>, int *, int)'
    -stl_algo.h:1524:   instantiated from here
    -stl_algo.h:1377: no match for `_List_iterator<int,int &,int *> & -
    -  _List_iterator<int,int &,int *> &'
    +  

    Attempting to compile this code with Gnu C++ produces the following + compiler error:

    +
    +/usr/include/c++/4.1.2/bits/stl_algo.h: In function ‘void std::
    +  __insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with 
    +  _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::complex<float
    +  >*, std::vector<std::complex<float>, std::allocator<std::complex<
    +  float> > > >]’:
    +/usr/include/c++/4.1.2/bits/stl_algo.h:3066:   instantiated from ‘void 
    +  std::__inplace_stable_sort(_RandomAccessIterator, 
    +  _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::
    +  __normal_iterator<std::complex<float>*, std::vector<std::complex<
    +  float>, std::allocator<std::complex<float> > > >]’
    +/usr/include/c++/4.1.2/bits/stl_algo.h:3776:   instantiated from ‘void 
    +  std::stable_sort(_RandomAccessIterator, _RandomAccessIterator) [with 
    +  _RandomAccessIterator = __gnu_cxx::__normal_iterator<std::complex<float
    +  >*, std::vector<std::complex<float>, std::allocator<std::complex<
    +  float> > > >]’
    +bad_error_eg.cpp:8:   instantiated from here
    +/usr/include/c++/4.1.2/bits/stl_algo.h:2277: error: no match for 
    +  ‘operator<’ in ‘__val < __first. __gnu_cxx::__normal_iterator<
    +  _Iterator, _Container>::operator* [with _Iterator = std::complex<float
    +  >*, _Container = std::vector<std::complex<float>, std::allocator<
    +  std::complex<float> > >]()’
     
    -In this case, the fundamental error is that -std:list::iterator does not model the concept of -RandomAccessIterator. The list iterator is only bidirectional, not -fully random access (as would be a vector iterator). Unfortunately, -there is nothing in the error message to indicate this to the user. +

    In this case, the fundamental error is + that std:complex<float> does not model the LessThanComparable + concept. Unfortunately, there is nothing in the error message to + indicate that to the user.

    -

    -To a C++ programmer having enough experience with template libraries -the error may be obvious. However, for the uninitiated, there are several -reasons why this message would be hard to understand. +

    The error may be obvious to a C++ programmer having enough + experience with template libraries, but there are several reasons + why this message could be hard for the uninitiated to + understand:

    -
      -
    1. The location of the error, line 6 of bad_error_eg.cpp - is not pointed to by the error message, despite the fact that Gnu C++ - prints up to 4 levels deep in the instantiation stack. -
    2. There is no textual correlation between the error message and the - documented requirements for std::stable_sort() and for - -RandomAccessIterator. -
    3. The error message is overly long, listing functions internal - to the STL that the user does not (and should not!) know or care - about. -
    4. With so many internal library functions listed in the error - message, the programmer could easily infer that the error is due - to the library, rather than to his or her own code. -
    +
      +
    1. There is no textual correlation between the error message and the + documented requirements for std::stable_sort() and for LessThanComparable.
    2. -The following is an example of what we might expect from a more -informative message (and is in fact what the Boost Concept Checking -Library produces): +
    3. The error message is overly long, listing functions internal + to the STL (e.g. __insertion_sort) that the user + does not (and should not!) know or care about.
    4. -
      -boost/concept_check.hpp: In method `void LessThanComparableConcept
      -  <_List_iterator<int,int &,int *> >::~LessThanComparableConcept()':
      -boost/concept_check.hpp:334:   instantiated from `RandomAccessIteratorConcept
      -  <_List_iterator<int,int &,int *> >::~RandomAccessIteratorConcept()'
      -bad_error_eg.cpp:6:   instantiated from `stable_sort<_List_iterator
      -  <int,int &,int *> >(_List_iterator<int,int &,int *>, 
      -  _List_iterator<int,int &,int *>)'
      -boost/concept_check.hpp:209: no match for `_List_iterator<int,int &,int *> &
      -  < _List_iterator<int,int &,int *> &'
      +    
    5. With so many internal library functions listed in the error message, + the programmer could easily infer that the problem is in the library, + rather than in his or her own code.
    6. +
    + +

    The following is an example of what we might expect from a more + informative message (and is in fact what the Boost Concept Checking Library + produces):

    +
    +boost/concept_check.hpp: In destructor ‘boost::LessThanComparable<TT>::~
    +  LessThanComparable() [with TT = std::complex<float>]’:
    +boost/concept/detail/general.hpp:29:   instantiated from ‘static void boost::
    +  concept::requirement<Model>::failed() [with Model = boost::
    +  LessThanComparable<std::complex<float> >]’
    +boost/concept/requires.hpp:30:   instantiated from ‘boost::_requires_<void
    +  (*)(boost::LessThanComparable<std::complex<float> >)>’
    +bad_error_eg.cpp:8:   instantiated from here
    +boost/concept_check.hpp:236: error: no match for ‘operator<’ in ‘((boost::
    +  LessThanComparable<std::complex<float> >*)this)->boost::
    +  LessThanComparable<std::complex<float> >::a < ((boost::
    +  LessThanComparable<std::complex<float> >*)this)->boost::
    +  LessThanComparable<std::complex<float> >::b’
     
    -This message rectifies several of the shortcomings of the standard -error messages. +

    This message rectifies several of the shortcomings of the standard error + messages.

    -
      -
    • The location of the error, bad_error_eg.cpp:6 is - specified in the error message. -
    • The message refers explicitly to concepts that the user can look - up in the STL documentation ( -RandomAccessIterator). -
    • The error message is now much shorter and does not reveal - internal STL functions. -
    • The presence of concept_check.hpp in the error message - alerts the user to the fact that the error lies in the user code and - not in the library implementation. -
    +
      +
    • The message refers explicitly to concepts that the user can look up + in the STL documentation (LessThanComparable).
    • -

      History

      +
    • The error message is now much shorter and does not reveal + internal STL functions, nor indeed does it even point + to std::stable_sort.
    • -An earlier version of this concept checking system was developed by -the author while working at SGI in their C++ compiler and library -group. The earlier version is now part of the SGI STL distribution. The -boost concept checking library differs from the concept checking in -the SGI STL in that the definition of concept checking classes has -been greatly simplified, at the price of less helpful verbiage in the -error messages. +
    • The presence of concept_check.hpp in the error message + alerts the user to the fact that the error lies in the user code and not + in the library implementation.
    • +
    -

    Publications

    +

    History

    - +

    The first version of this concept checking system was developed + by Jeremy Siek while working at SGI in their C++ compiler and + library group. That version is now part of the SGI STL + distribution. The system originally introduced as the boost concept + checking library differs from concept checking in the SGI STL in + that the definition of concept checking classes was greatly + simplified, at the price of less helpful verbiage in the error + messages. In 2006 the system was rewritten (preserving backward + compatibility) by Dave Abrahams to be easier to use, more similar to + the proposed concept support the C++ core language, and to give + better error messages. +

    -

    Acknowledgements

    +

    Publications

    -The idea to use function pointers to cause instantiation is due to -Alexander Stepanov. I am not sure of the origin of the idea to use -expressions to do up-front checking of templates, but it did appear in -D&E[ -2]. -Thanks to Matt Austern for his excellent documentation and -organization of the STL concepts, upon which these concept checks -are based. Thanks to Boost members for helpful comments and -reviews. + +

    Acknowledgements

    The idea to use function + pointers to cause instantiation is due to Alexander Stepanov. We are not sure + of the origin of the idea to use expressions to do up-front checking of + templates, but it did appear in D&E[ 2]. Thanks to Matt + Austern for his excellent documentation and organization of the STL + concepts, upon which these concept checks are based. Thanks to Boost + members for helpful comments and reviews. -

    -Next: Using Concept Checks +

    Next: Using Concept + Checks

    +
    -
    -
    - - -
    Copyright © 2000 -Jeremy Siek(jsiek@osl.iu.edu) -Andrew Lumsdaine(lums@osl.iu.edu) -
    + + + - - + + +
    Copyright © 2000Jeremy Siek(jsiek@osl.iu.edu) Andrew + Lumsdaine(lums@osl.iu.edu), + 2007 David Abrahams. +
    + + diff --git a/concept_covering.htm b/concept_covering.htm index dfadd60..96c3208 100644 --- a/concept_covering.htm +++ b/concept_covering.htm @@ -1,126 +1,125 @@ - - - -Concept Covering and Archetypes - -C++ Boost + -
    + + + + + -

    Concept Covering and Archetypes

    + + -We have discussed how it is important to select the minimal -requirements (concepts) for the inputs to a component, but it is -equally important to verify that the chosen concepts cover the -algorithm. That is, any possible user error should be caught by the -concept checks and not let slip through. Concept coverage can be -verified through the use of archetype classes. An archetype -class is an exact implementation of the interface associated with a -particular concept. The run-time behavior of the archetype class is -not important, the functions can be left empty. A simple test program -can then be compiled with the archetype classes as the inputs to the -component. If the program compiles then one can be sure that the -concepts cover the component. + Concept Covering and Archetypes + + + -The following code shows the archetype class for the Input -Iterator concept. Some care must be taken to ensure that the -archetype is an exact match to the concept. For example, the concept -states that the return type of operator*() must be -convertible to the value type. It does not state the more stringent -requirement that the return type be T& or const -T&. That means it would be a mistake to use T& -or const T& for the return type of the archetype -class. The correct approach is to create an artificial return type -that is convertible to T, as we have done here with -reference. The validity of the archetype class test is -completely dependent on it being an exact match with the concept, -which must be verified by careful (manual) inspection. + + C++ Boost
    -
    -  template <class T>
    -  class input_iterator_archetype
    -  {
    -  private:
    -    typedef input_iterator_archetype self;
    -  public:
    -    typedef std::input_iterator_tag iterator_category;
    -    typedef T value_type;
    -    struct reference {
    -      operator const value_type&() const { return static_object<T>::get(); }
    -    };
    -    typedef const T* pointer;
    -    typedef std::ptrdiff_t difference_type;
    -    self& operator=(const self&) { return *this;  }
    -    bool operator==(const self&) const { return true; }
    -    bool operator!=(const self&) const { return true; }
    -    reference operator*() const { return reference(); }
    -    self& operator++() { return *this; }
    -    self operator++(int) { return *this; }
    +  

    Concept Covering and + Archetypes

    + +

    We have discussed how it is important to select the minimal requirements + (concepts) for the inputs to a component, but it is equally important to + verify that the chosen concepts cover the algorithm. That is, any + possible user error should be caught by the concept checks and not let slip + through. Concept coverage can be verified through the use of archetype + classes. An archetype class is an exact implementation of the interface + associated with a particular concept. The run-time behavior of the + archetype class is not important, the functions can be left empty. A simple + test program can then be compiled with the archetype classes as the inputs + to the component. If the program compiles then one can be sure that the + concepts cover the component. The following code shows the archetype class + for the Input + Iterator concept. Some care must be taken to ensure that the archetype + is an exact match to the concept. For example, the concept states that the + return type of operator*() must be convertible to the value type. + It does not state the more stringent requirement that the return type be + T& or const T&. That means it would be a mistake + to use T& or const T& for the return type of the + archetype class. The correct approach is to create an artificial return + type that is convertible to T, as we have done here with + reference. The validity of the archetype class test is completely + dependent on it being an exact match with the concept, which must be + verified by careful (manual) inspection.

    +
    +template <class T>
    +class input_iterator_archetype
    +{
    +private:
    +  typedef input_iterator_archetype self;
    +public:
    +  typedef std::input_iterator_tag iterator_category;
    +  typedef T value_type;
    +  struct reference {
    +    operator const value_type&() const { return static_object<T>::get(); }
       };
    +  typedef const T* pointer;
    +  typedef std::ptrdiff_t difference_type;
    +  self& operator=(const self&) { return *this;  }
    +  bool operator==(const self&) const { return true; }
    +  bool operator!=(const self&) const { return true; }
    +  reference operator*() const { return reference(); }
    +  self& operator++() { return *this; }
    +  self operator++(int) { return *this; }
    +};
     
    -Generic algorithms are often tested by being instantiated with a -number of common input types. For example, one might apply -std::stable_sort() with basic pointer types as the iterators. -Though appropriate for testing the run-time behavior of the algorithm, -this is not helpful for ensuring concept coverage because C++ types -never match particular concepts, they often provide much more than the -minimal functionality required by any one concept. That is, even -though the function template compiles with a given type, the concept -requirements may still fall short of covering the functions actual -requirements. This is why it is important to compile with archetype -classes in addition to testing with common input types. +

    Generic algorithms are often tested by being instantiated with a number + of common input types. For example, one might apply + std::stable_sort() with basic pointer types as the iterators. + Though appropriate for testing the run-time behavior of the algorithm, this + is not helpful for ensuring concept coverage because C++ types never match + particular concepts exactly. Instead, they often provide more than the + minimal functionality required by any one concept. Even though the function + template has concept checks, and compiles with a given type, the checks may + still fall short of covering all the functionality that is actually used. + This is why it is important to compile with archetype classes in addition + to testing with common input types.

    -

    -The following is an excerpt from stl_concept_covering.cpp -that shows how archetypes can be used to check the requirement -documentation for - -std::stable_sort(). In this case, it looks like the CopyConstructible and Assignable requirements were -forgotten in the SGI STL documentation (try removing those -archetypes). The Boost archetype classes have been designed so that -they can be layered. In this example the value type of the iterator -is composed out of three archetypes. In the archetype class reference -below, template parameters named Base indicate where the -layered archetype can be used. - -

    -  {
    -    typedef less_than_comparable_archetype< 
    -        sgi_assignable_archetype<> > ValueType;
    -    random_access_iterator_archetype<ValueType> ri;
    -    std::stable_sort(ri, ri);
    -  }
    +  

    The following is an excerpt from stl_concept_covering.cpp that + shows how archetypes can be used to check the requirement documentation for + std::stable_sort(). + In this case, it looks like the CopyConstructible and Assignable requirements were forgotten in + the SGI STL documentation (try removing those archetypes). The Boost + archetype classes have been designed so that they can be layered. In this + example the value type of the iterator is composed out of three archetypes. + In the archetype class + reference, template parameters named Base indicate where the + layered archetype paradigm can be used.

    +
    +{
    +  typedef less_than_comparable_archetype< 
    +      sgi_assignable_archetype<> > ValueType;
    +  random_access_iterator_archetype<ValueType> ri;
    +  std::stable_sort(ri, ri);
    +}
     
    -Next: Programming with Concepts
    -Prev: Creating Concept Checking Classes +

    Next: Programming with + Concepts
    + Prev: Creating Concept Checking + Classes
    +


    -
    -
    - - -
    Copyright © 2000 -Jeremy Siek(jsiek@osl.iu.edu) -Andrew Lumsdaine(lums@osl.iu.edu) -
    + + + - - + +
    Copyright © 2000Jeremy Siek(jsiek@osl.iu.edu) Andrew + Lumsdaine(lums@osl.iu.edu), + 2007 David Abrahams. +
    + + diff --git a/creating_concepts.htm b/creating_concepts.htm index d19ca01..f6cca8f 100644 --- a/creating_concepts.htm +++ b/creating_concepts.htm @@ -1,110 +1,157 @@ - - - -Creating Concept Checking Classes - -C++ Boost + -
    + + + + + + + + -

    Creating Concept Checking Classes

    + Creating Concept Checking Classes + + -As an example of how to create a concept checking class, we look -at how to create the corresponding checks for the - -RandomAccessIterator concept. First, as a convention we name the -concept checking class after the concept, and add the suffix -``Concept''. Next we must define a member function named -constraints() in which we will exercise the valid expressions -of the concept. function_requires() expects this function's -signature to appear exactly as it is appears below: a void -non-const member function with no parameters. + + C++ Boost
    -

    -The first part of the constraints() function includes -the requirements that correspond to the refinement relationship -between -RandomAccessIterator and the concepts which it builds upon: - -BidirectionalIterator and - -LessThanComparable. We could have instead used -BOOST_CLASS_REQUIRE and placed these requirements in the class -body, however BOOST_CLASS_REQUIRE uses C++ language features that -are less portable. +

    Creating + Concept Checking Classes

    -

    -Next we check that the iterator_category of the iterator is -either std::random_access_iterator_tag or a derived class. -After that we write out some code that corresponds to the valid -expressions of the -RandomAccessIterator concept. Typedefs can also be added to -enforce the associated types of the concept. +

    As an example of how to create a concept checking class template, we + look at how to create the corresponding checks for the InputIterator concept. + The complete definition is here:

    +
    +template <class X>
    +struct InputIterator
    +  : Assignable<X>, EqualityComparable<X>
    +{
    + private:
    +    typedef std::iterator_traits<X> t;
    + public:
    +    typedef typename t::value_type value_type;
    +    typedef typename t::difference_type difference_type;
    +    typedef typename t::reference reference;
    +    typedef typename t::pointer pointer;
    +    typedef typename t::iterator_category iterator_category;
     
    -
    -  template <class Iter>
    -  struct RandomAccessIteratorConcept
    -  {
    -    void constraints() {
    -      function_requires< BidirectionalIteratorConcept<Iter> >();
    -      function_requires< LessThanComparableConcept<Iter> >();
    -      function_requires< ConvertibleConcept<
    -        typename std::iterator_traits<Iter>::iterator_category,
    -        std::random_access_iterator_tag> >();
    -
    -      i += n;
    -      i = i + n; i = n + i;
    -      i -= n;
    -      i = i - n;
    -      n = i - j;
    -      i[n];
    +    BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
    +    BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
    +        
    +    BOOST_CONCEPT_USAGE(InputIterator)
    +    {
    +        X j(i);             // require copy construction
    +        same_type(*i++,v);  // require postincrement-dereference returning value_type
    +        X& x = ++j;         // require preincrement returning X&
         }
    -    Iter i, j;
    -    typename std::iterator_traits<Iter>::difference_type n;
    -  };
    +    
    + private:
    +    X i;
    +    value_type v;
    +
    +    // Type deduction will fail unless the arguments have the same type.
    +    template <typename T>
    +    void same_type(T const&, T const&);
    +};
    +
    + +

    Walkthrough

    + +

    First, as a convention we name the concept checking class after the + concept. Next, since InputIterator is a refinement of Assignable and + EqualityComparable, we derive its concept checking class from the checking + classes for those other concepts. The library will automatically check for + conformance to Assignable and EqualityComparable whenever it checks the + InputIterator concept.

    + +

    Next, we declare the concept's associated types + as member typedefs. The associated difference type is required to be a + signed integer, and the iterator category has to be convertible to + std::input_iterator_tag, so we assert those relationships. The syntax for + accessing associated types through the concept-checking template mirrors + the proposed + syntax for associated type access in C++0x Finally, we use the + BOOST_CONCEPT_USAGE macro to declare the function that + exercises all the concept's valid expressions. Note that at this point you + may sometimes need to be a little creative: for example, to check that + *i++ returns the iterator's value type, we pass both values to + the same_type member function template, which requires both + arguments to have the same type, modulo references and cv-qualification. + It's an imperfect check, but it's better than nothing.

    + +

    Values for Usage Patterns Should Be Data Members

    + +

    You may be wondering why we declared i and v + as data members in the example above. Why didn't we simply write the + following?

    +
    +BOOST_CONCEPT_USAGE(InputIterator)
    +{
    +    X i;                // create the values we need
    +    value_type v;
    +
    +    X j(i);             // require copy construction
    +    same_type(*i++,v);  // require postincrement-dereference returning value_type
    +    X& x = ++j;         // require preincrement returning X&
     }
     
    -One potential pitfall in designing concept checking classes is using -more expressions in the constraint function than necessary. For -example, it is easy to accidentally use the default constructor to -create the objects that will be needed in the expressions (and not all -concepts require a default constructor). This is the reason we write -the constraint function as a member function of a class. The objects -involved in the expressions are declared as data members of the class. -Since objects of the constraints class template are never -instantiated, the default constructor for the concept checking class -is never instantiated. Hence the data member's default constructors -are never instantiated (C++ Standard Section 14.7.1 9). +

    Unfortunately, that code wouldn't have worked out so well, because it + unintentionally imposes the requirement that X and its value + type are both default-constructible. On the other hand, since instances of + the InputIterator template will never be constructed, the + compiler never has to check how its data members will be constructed (C++ + Standard Section 14.7.1 9). For that reason you should always + declare values needed for usage patterns as data members.

    -

    -Next: Concept Covering and Archetypes
    -Prev: Using Concept Checks +

    These sorts of errors in concept definitions can be detected by the use + of Concept Archetypes, but it's always + better to avoid them pre-emptively.

    +

    Similarity to Proposed C++0x Language Support for Concepts

    -
    -
    - - -
    Copyright © 2000 -Jeremy Siek(jsiek@osl.iu.edu) -Andrew Lumsdaine(lums@osl.iu.edu) -
    +

    This library's syntaxes for concept refinement and for access of + associated types mirrors the corresponding proposed + syntaxes in C++0x. However, C++0x will use + “signatures” rather than usage patterns to + describe the valid operations on types participating in a concept, so when + converting your concept checking classes into language-supported concepts, + you'll need to translate your usage function into a series of + signatures.

    - - +

    Next: Concept Covering and + Archetypes
    + Prev: Using Concept + Checks

    +
    + + + + + + +
    Copyright © 2000Jeremy Siek(jsiek@osl.iu.edu) Andrew + Lumsdaine(lums@osl.iu.edu), + 2007 David Abrahams. +
    + + diff --git a/fake_sort.hpp b/fake_sort.hpp index bdac487..131bcc7 100755 --- a/fake_sort.hpp +++ b/fake_sort.hpp @@ -13,7 +13,7 @@ namespace fake using namespace boost; template - BOOST_CONCEPT_WHERE( + BOOST_CONCEPT_REQUIRES( ((Mutable_RandomAccessIterator)) ((LessThanComparable::value_type>)) diff --git a/implementation.htm b/implementation.htm index b2c3db9..6df94ca 100644 --- a/implementation.htm +++ b/implementation.htm @@ -1,50 +1,59 @@ - - - -Concept Checking Implementation - -C++ Boost + -
    + + + + + + + + + -

    Implementation

    + Concept Checking Implementation + -Ideally we would like to catch, and indicate, the concept violation at -the point of instantiation. As mentioned in D&E[2], the error -can be caught by exercising all of the requirements needed by the -function template. Exactly how the requirements (the valid -expressions in particular) are exercised is a tricky issue, since we -want the code to be compiled --- but not executed. Our -approach is to exercise the requirements in a separate function that -is assigned to a function pointer. In this case, the compiler will -instantiate the function but will not actually invoke it. In -addition, an optimizing compiler will remove the pointer assignment as -``dead code'' (though the run-time overhead added by the assignment -would be trivial in any case). It might be conceivable for a compiler -to skip the semantic analysis and compilation of the constraints -function in the first place, which would make our function pointer -technique ineffective. However, this is unlikely because removal of -unnecessary code and functions is typically done in later stages of a -compiler. We have successfully used the function pointer technique -with GNU C++, Microsoft Visual C++, and several EDG-based compilers -(KAI C++, SGI MIPSpro). The following code shows how this technique -can be applied to the std::stable_sort() function: + + C++ Boost
    -
    +  

    Warning

    + +

    This documentation is out-of-date; similar but + newer implementation techniques are now used. This documentation + also refers to components and protocols in the library's old + interace such as BOOST_CLASS_REQUIRES + and constraints() functions, which are still supported + but deprecated.

    + +

    Implementation

    + +

    Ideally we would like to catch, and indicate, the concept violation at + the point of instantiation. As mentioned in D&E[2], the error can be + caught by exercising all of the requirements needed by the function + template. Exactly how the requirements (the valid expressions in + particular) are exercised is a tricky issue, since we want the code to be + compiled—but not executed. Our approach is to exercise the + requirements in a separate function that is assigned to a function pointer. + In this case, the compiler will instantiate the function but will not + actually invoke it. In addition, an optimizing compiler will remove the + pointer assignment as ``dead code'' (though the run-time overhead added by + the assignment would be trivial in any case). It might be conceivable for a + compiler to skip the semantic analysis and compilation of the constraints + function in the first place, which would make our function pointer + technique ineffective. However, this is unlikely because removal of + unnecessary code and functions is typically done in later stages of a + compiler. We have successfully used the function pointer technique with GNU + C++, Microsoft Visual C++, and several EDG-based compilers (KAI C++, SGI + MIPSpro). The following code shows how this technique can be applied to the + std::stable_sort() function:

    +
       template <class RandomAccessIterator>
       void stable_sort_constraints(RandomAccessIterator i)
       {
    @@ -57,24 +66,23 @@ can be applied to the std::stable_sort() function:
       void stable_sort(RandomAccessIterator first, RandomAccessIterator last)
       {
         typedef void (*fptr_type)(RandomAccessIterator);
    -    fptr_type x = &stable_sort_constraints;
    +    fptr_type x = &stable_sort_constraints;
         ...
       }
     
    -There is often a large set of requirements that need to be checked, -and it would be cumbersome for the library implementor to write -constraint functions like stable_sort_constraints() for every -public function. Instead, we group sets of valid expressions -together, according to the definitions of the corresponding concepts. -For each concept we define a concept checking class template where the -template parameter is for the type to be checked. The class contains -a contraints() member function which exercises all of the -valid expressions of the concept. The objects used in the constraints -function, such as n and i, are declared as data -members of the concept checking class. - -
    +  

    There is often a large set of requirements that need to be checked, and + it would be cumbersome for the library implementor to write constraint + functions like stable_sort_constraints() for every public + function. Instead, we group sets of valid expressions together, according + to the definitions of the corresponding concepts. For each concept we + define a concept checking class template where the template parameter is + for the type to be checked. The class contains a contraints() + member function which exercises all of the valid expressions of the + concept. The objects used in the constraints function, such as n + and i, are declared as data members of the concept checking + class.

    +
       template <class Iter>
       struct RandomAccessIteratorConcept
       {
    @@ -90,18 +98,14 @@ members of the concept checking class.
       };
     
    -We can still use the function pointer mechanism to cause instantiation -of the constraints function, however now it will be a member function -pointer. To make it easy for the library implementor to invoke the -concept checks, we wrap the member function pointer mechanism in a -function named function_requires(). The following code -snippet shows how to use function_requires() to make sure -that the iterator is a - -RandomAccessIterator. - -
    +  

    We can still use the function pointer mechanism to cause instantiation + of the constraints function, however now it will be a member function + pointer. To make it easy for the library implementor to invoke the concept + checks, we wrap the member function pointer mechanism in a function named + function_requires(). The following code snippet shows how to use + function_requires() to make sure that the iterator is a RandomAccessIterator.

    +
       template <class Iter>
       void stable_sort(Iter first, Iter last)
       {
    @@ -110,16 +114,15 @@ RandomAccessIterator.
       }
     
    -The definition of the function_requires() is as follows. The -Concept is the concept checking class that has been -instantiated with the modeling type. We assign the address of the -constraints member function to the function pointer x, which -causes the instantiation of the constraints function and checking of -the concept's valid expressions. We then assign x to -x to avoid unused variable compiler warnings, and wrap -everything in a do-while loop to prevent name collisions. - -
    +  

    The definition of the function_requires() is as follows. The + Concept is the concept checking class that has been instantiated + with the modeling type. We assign the address of the constraints member + function to the function pointer x, which causes the instantiation + of the constraints function and checking of the concept's valid + expressions. We then assign x to x to avoid unused + variable compiler warnings, and wrap everything in a do-while loop to + prevent name collisions.

    +
       template <class Concept>
       void function_requires()
       {
    @@ -128,17 +131,16 @@ everything in a do-while loop to prevent name collisions.
       }
     
    -To check the type parameters of class templates, we provide the -BOOST_CLASS_REQUIRE macro which can be used inside the body of a -class definition (whereas function_requires() can only be used -inside of a function body). This macro declares a nested class -template, where the template parameter is a function pointer. We then -use the nested class type in a typedef with the function pointer type -of the constraint function as the template argument. We use the -type_var and concept names in the nested class and -typedef names to help prevent name collisions. - -
    +  

    To check the type parameters of class templates, we provide the + BOOST_CLASS_REQUIRE macro which can be used inside the body of a + class definition (whereas function_requires() can only be used + inside of a function body). This macro declares a nested class template, + where the template parameter is a function pointer. We then use the nested + class type in a typedef with the function pointer type of the constraint + function as the template argument. We use the type_var and + concept names in the nested class and typedef names to help + prevent name collisions.

    +
     #define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
       typedef void (ns::concept <type_var>::* func##type_var##concept)(); \
       template <func##type_var##concept _Tp1> \
    @@ -148,14 +150,12 @@ typedef names to help prevent name collisions.
         concept_checking_typedef_##type_var##concept
     
    -In addition, there are versions of BOOST_CLASS_REQUIRE that -take more arguments, to handle concepts that include interactions -between two or more types. BOOST_CLASS_REQUIRE was not used -in the implementation of the BCCL concept checks because some -compilers do not implement template parameters of function pointer -type. - - +-->

    -

    -Next: Reference
    -Prev: Programming With Concepts +

    Next: Reference
    + Prev: Programming With + Concepts

    +
    -
    -
    - - -
    Copyright © 2000 -Jeremy Siek(jsiek@osl.iu.edu) -Andrew Lumsdaine(lums@osl.iu.edu) -
    + + + - - + +
    Copyright © 2000Jeremy Siek(jsiek@osl.iu.edu) Andrew + Lumsdaine(lums@osl.iu.edu), + 2007 David Abrahams. +
    + + diff --git a/include/boost/concept/usage.hpp b/include/boost/concept/usage.hpp index 399bd4c..9af8ca3 100755 --- a/include/boost/concept/usage.hpp +++ b/include/boost/concept/usage.hpp @@ -21,9 +21,20 @@ struct usage_requirements ~usage_requirements() { ((Model*)0)->~Model(); } }; -# define BOOST_CONCEPT_USAGE(model) \ - BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements)); \ - ~model() +# if BOOST_WORKAROUND(__GNUC__, <= 3) + +# define BOOST_CONCEPT_USAGE(model) \ + model(); /* at least 2.96 and 3.4.3 both need this :( */ \ + BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements)); \ + ~model() + +# else + +# define BOOST_CONCEPT_USAGE(model) \ + BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements)); \ + ~model() + +# endif # endif diff --git a/include/boost/concept/where.hpp b/include/boost/concept/where.hpp index c91c1f9..5570b64 100755 --- a/include/boost/concept/where.hpp +++ b/include/boost/concept/where.hpp @@ -1,8 +1,8 @@ // Copyright David Abrahams 2006. 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) -#ifndef BOOST_CONCEPT_WHERE_DWA2006430_HPP -# define BOOST_CONCEPT_WHERE_DWA2006430_HPP +#ifndef BOOST_CONCEPT_REQUIRES_DWA2006430_HPP +# define BOOST_CONCEPT_REQUIRES_DWA2006430_HPP # include # include @@ -12,7 +12,7 @@ namespace boost { // Template for use in handwritten assertions template -struct where_ : More +struct requires_ : More { # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) typedef typename More::type type; @@ -23,41 +23,52 @@ struct where_ : More // Template for use by macros, where models must be wrapped in parens. // This isn't in namespace detail to keep extra cruft out of resulting // error messages. -template -struct _where_ : More +template +struct _requires_ { -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - typedef typename More::type type; -# endif + enum { value = 0 }; BOOST_CONCEPT_ASSERT_FN(ModelFn); }; -#define BOOST_CONCEPT_WHERE_OPEN(r,data,t) ::boost::_where_ +template +struct Requires_ : ::boost::parameter::aux::unaryfunptr_arg_type +{ +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typedef typename ::boost::parameter::aux::unaryfunptr_arg_type::type type; +# endif +}; + + +#define BOOST_CONCEPT_REQUIRES_(r,data,t) + (::boost::_requires_::value) #if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300) -# define BOOST_CONCEPT_WHERE(models, result) \ +# define BOOST_CONCEPT_REQUIRES(models, result) \ typename ::boost::parameter::aux::unaryfunptr_arg_type::type #elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // Same thing as below without the initial typename -# define BOOST_CONCEPT_WHERE(models, result) \ - BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \ +# define BOOST_CONCEPT_REQUIRES(models, result) \ + ::boost::Requires_< \ + (0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \ ::boost::parameter::aux::unaryfunptr_arg_type \ - BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type + >::type #else // This just ICEs on MSVC6 :( -# define BOOST_CONCEPT_WHERE(models, result) \ - typename BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_OPEN, ~, models) \ - ::boost::parameter::aux::unaryfunptr_arg_type \ - BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_WHERE_CLOSE, ~, models)::type +# define BOOST_CONCEPT_REQUIRES(models, result) \ + typename ::boost::Requires_< \ + (0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \ + void(*)result \ + >::type #endif +// C++0x proposed syntax changed. This supports an older usage +#define BOOST_CONCEPT_WHERE(models,result) BOOST_CONCEPT_REQUIRES(models,result) + } // namespace boost::concept_check -#endif // BOOST_CONCEPT_WHERE_DWA2006430_HPP +#endif // BOOST_CONCEPT_REQUIRES_DWA2006430_HPP diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp index 555f2b4..4e9fddf 100644 --- a/include/boost/concept_check.hpp +++ b/include/boost/concept_check.hpp @@ -62,9 +62,6 @@ namespace boost // BOOST_concept(Integer, (T)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Integer(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(Integer) { x.error_type_must_be_an_integer_type(); @@ -90,9 +87,6 @@ namespace boost # endif BOOST_concept(SignedInteger,(T)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - SignedInteger(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(SignedInteger) { x.error_type_must_be_a_signed_integer_type(); } @@ -110,9 +104,6 @@ namespace boost # endif BOOST_concept(UnsignedInteger,(T)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - UnsignedInteger(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(UnsignedInteger) { x.error_type_must_be_an_unsigned_integer_type(); } @@ -135,9 +126,6 @@ namespace boost BOOST_concept(DefaultConstructible,(TT)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - DefaultConstructible(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(DefaultConstructible) { TT a; // require default constructor ignore_unused_variable_warning(a); @@ -146,13 +134,9 @@ namespace boost BOOST_concept(Assignable,(TT)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Assignable(); // at least 2.96 and 3.4.3 both need this :( -#endif - BOOST_CONCEPT_USAGE(Assignable) { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL - a = a; // require assignment operator + a = a; // require assignment operator #endif const_constraints(a); } @@ -166,12 +150,9 @@ namespace boost TT a; }; + BOOST_concept(CopyConstructible,(TT)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - CopyConstructible(); // at least 2.96 and 3.4.3 both need this :( -#endif - BOOST_CONCEPT_USAGE(CopyConstructible) { TT a(b); // require copy constructor TT* ptr = &a; // require address of operator @@ -191,10 +172,6 @@ namespace boost // The SGI STL version of Assignable requires copy constructor and operator= BOOST_concept(SGIAssignable,(TT)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - SGIAssignable(); // at least 2.96 and 3.4.3 both need this :( -#endif - BOOST_CONCEPT_USAGE(SGIAssignable) { TT b(a); #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL @@ -216,9 +193,6 @@ namespace boost BOOST_concept(Convertible,(X)(Y)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Convertible(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(Convertible) { Y y = x; ignore_unused_variable_warning(y); @@ -244,9 +218,6 @@ namespace boost BOOST_concept(EqualityComparable,(TT)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - EqualityComparable(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(EqualityComparable) { require_boolean_expr(a == b); require_boolean_expr(a != b); @@ -257,9 +228,6 @@ namespace boost BOOST_concept(LessThanComparable,(TT)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - LessThanComparable(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(LessThanComparable) { require_boolean_expr(a < b); } @@ -270,9 +238,6 @@ namespace boost // This is equivalent to SGI STL's LessThanComparable. BOOST_concept(Comparable,(TT)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Comparable(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(Comparable) { require_boolean_expr(a < b); require_boolean_expr(a > b); @@ -283,18 +248,6 @@ namespace boost TT a, b; }; -#if BOOST_WORKAROUND(__GNUC__, <= 3) -#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ - BOOST_concept(NAME, (First)(Second)) \ - { \ - NAME(); \ - BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ - private: \ - bool constraints_() { return a OP b; } \ - First a; \ - Second b; \ - } -#else #define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (First)(Second)) \ { \ @@ -304,20 +257,7 @@ namespace boost First a; \ Second b; \ } -#endif -#if BOOST_WORKAROUND(__GNUC__, <= 3) -#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ - BOOST_concept(NAME, (Ret)(First)(Second)) \ - { \ - NAME(); \ - BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ - private: \ - Ret constraints_() { return a OP b; } \ - First a; \ - Second b; \ - } -#else #define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ BOOST_concept(NAME, (Ret)(First)(Second)) \ { \ @@ -327,7 +267,6 @@ namespace boost First a; \ Second b; \ } -#endif BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp); BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp); @@ -347,9 +286,6 @@ namespace boost BOOST_concept(Generator,(Func)(Return)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Generator(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(Generator) { test(is_void()); } private: @@ -370,9 +306,6 @@ namespace boost BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - UnaryFunction(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void()); } private: @@ -394,9 +327,6 @@ namespace boost BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - BinaryFunction(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void()); } private: void test(boost::mpl::false_) @@ -418,9 +348,6 @@ namespace boost BOOST_concept(UnaryPredicate,(Func)(Arg)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - UnaryPredicate(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(UnaryPredicate) { require_boolean_expr(f(arg)); // require operator() returning bool } @@ -431,9 +358,6 @@ namespace boost BOOST_concept(BinaryPredicate,(Func)(First)(Second)) { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(BinaryPredicate) { require_boolean_expr(f(a, b)); // require operator() returning bool } @@ -447,9 +371,6 @@ namespace boost BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) : BinaryPredicate { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Const_BinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(Const_BinaryPredicate) { const_constraints(f); } @@ -468,9 +389,6 @@ namespace boost { typedef typename Func::result_type result_type; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - AdaptableGenerator(); // at least 2.96 and 3.4.3 both need this :( -#endif BOOST_CONCEPT_USAGE(AdaptableGenerator) { BOOST_CONCEPT_ASSERT((Convertible)); @@ -483,9 +401,6 @@ namespace boost typedef typename Func::argument_type argument_type; typedef typename Func::result_type result_type; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - AdaptableUnaryFunction(); // at least 2.96 and 3.4.3 both need this :( -#endif ~AdaptableUnaryFunction() { BOOST_CONCEPT_ASSERT((Convertible)); @@ -505,9 +420,6 @@ namespace boost typedef typename Func::second_argument_type second_argument_type; typedef typename Func::result_type result_type; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - AdaptableBinaryFunction(); // at least 2.96 and 3.4.3 both need this :( -#endif ~AdaptableBinaryFunction() { BOOST_CONCEPT_ASSERT((Convertible)); @@ -520,18 +432,12 @@ namespace boost : UnaryPredicate , AdaptableUnaryFunction { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - AdaptablePredicate(); // at least 2.96 and 3.4.3 both need this :( -#endif }; BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second)) : BinaryPredicate , AdaptableBinaryFunction { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - AdaptableBinaryPredicate(); // at least 2.96 and 3.4.3 both need this :( -#endif }; //=========================================================================== @@ -547,10 +453,7 @@ namespace boost typedef typename boost::detail::iterator_traits::pointer pointer; typedef typename boost::detail::iterator_traits::iterator_category iterator_category; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - InputIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~InputIterator() + BOOST_CONCEPT_USAGE(InputIterator) { BOOST_CONCEPT_ASSERT((SignedInteger)); BOOST_CONCEPT_ASSERT((Convertible)); @@ -567,10 +470,7 @@ namespace boost BOOST_concept(OutputIterator,(TT)(ValueT)) : Assignable { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - OutputIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~OutputIterator() { + BOOST_CONCEPT_USAGE(OutputIterator) { ++i; // require preincrement operator i++; // require postincrement operator @@ -584,10 +484,7 @@ namespace boost BOOST_concept(ForwardIterator,(TT)) : InputIterator { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - ForwardIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~ForwardIterator() + BOOST_CONCEPT_USAGE(ForwardIterator) { BOOST_CONCEPT_ASSERT((Convertible< BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category @@ -605,10 +502,7 @@ namespace boost BOOST_concept(Mutable_ForwardIterator,(TT)) : ForwardIterator { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Mutable_ForwardIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Mutable_ForwardIterator() { + BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) { *i++ = *i; // require postincrement and assignment } private: @@ -618,10 +512,7 @@ namespace boost BOOST_concept(BidirectionalIterator,(TT)) : ForwardIterator { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~BidirectionalIterator() + BOOST_CONCEPT_USAGE(BidirectionalIterator) { BOOST_CONCEPT_ASSERT((Convertible< BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category @@ -639,10 +530,7 @@ namespace boost : BidirectionalIterator , Mutable_ForwardIterator { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Mutable_BidirectionalIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Mutable_BidirectionalIterator() + BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator) { *i-- = *i; // require postdecrement and assignment } @@ -654,10 +542,7 @@ namespace boost : BidirectionalIterator , Comparable { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~RandomAccessIterator() + BOOST_CONCEPT_USAGE(RandomAccessIterator) { BOOST_CONCEPT_ASSERT((Convertible< BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category @@ -682,10 +567,7 @@ namespace boost : RandomAccessIterator , Mutable_BidirectionalIterator { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Mutable_RandomAccessIterator(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Mutable_RandomAccessIterator() + BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator) { i[n] = *i; // require element access and assignment } @@ -707,10 +589,7 @@ namespace boost typedef typename C::const_pointer const_pointer; typedef typename C::const_iterator const_iterator; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Container(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Container() + BOOST_CONCEPT_USAGE(Container) { BOOST_CONCEPT_ASSERT((InputIterator)); const_constraints(c); @@ -737,10 +616,7 @@ namespace boost typedef typename C::iterator iterator; typedef typename C::pointer pointer; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Mutable_Container(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Mutable_Container() + BOOST_CONCEPT_USAGE(Mutable_Container) { BOOST_CONCEPT_ASSERT(( Assignable)); @@ -760,10 +636,7 @@ namespace boost BOOST_concept(ForwardContainer,(C)) : Container { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - ForwardContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~ForwardContainer() + BOOST_CONCEPT_USAGE(ForwardContainer) { BOOST_CONCEPT_ASSERT(( ForwardIterator< @@ -776,10 +649,7 @@ namespace boost : ForwardContainer , Mutable_Container { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Mutable_ForwardContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Mutable_ForwardContainer() + BOOST_CONCEPT_USAGE(Mutable_ForwardContainer) { BOOST_CONCEPT_ASSERT(( Mutable_ForwardIterator< @@ -795,10 +665,7 @@ namespace boost C::const_reverse_iterator const_reverse_iterator; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~ReversibleContainer() + BOOST_CONCEPT_USAGE(ReversibleContainer) { BOOST_CONCEPT_ASSERT(( BidirectionalIterator< @@ -823,10 +690,7 @@ namespace boost { typedef typename C::reverse_iterator reverse_iterator; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Mutable_ReversibleContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Mutable_ReversibleContainer() + BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer) { typedef typename Mutable_ForwardContainer::iterator iterator; BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator)); @@ -845,10 +709,7 @@ namespace boost typedef typename C::size_type size_type; typedef typename C::const_reference const_reference; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~RandomAccessContainer() + BOOST_CONCEPT_USAGE(RandomAccessContainer) { BOOST_CONCEPT_ASSERT(( RandomAccessIterator< @@ -875,10 +736,7 @@ namespace boost private: typedef Mutable_RandomAccessContainer self; public: -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Mutable_RandomAccessContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Mutable_RandomAccessContainer() + BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer) { BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator)); BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator)); @@ -900,10 +758,7 @@ namespace boost // ... so why aren't we following the standard? --DWA , DefaultConstructible { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - Sequence(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~Sequence() + BOOST_CONCEPT_USAGE(Sequence) { S c(n), @@ -940,10 +795,7 @@ namespace boost BOOST_concept(FrontInsertionSequence,(S)) : Sequence { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - FrontInsertionSequence(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~FrontInsertionSequence() + BOOST_CONCEPT_USAGE(FrontInsertionSequence) { c.push_front(t); c.pop_front(); @@ -956,10 +808,7 @@ namespace boost BOOST_concept(BackInsertionSequence,(S)) : Sequence { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - BackInsertionSequence(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~BackInsertionSequence() + BOOST_CONCEPT_USAGE(BackInsertionSequence) { c.push_back(t); c.pop_back(); @@ -986,10 +835,7 @@ namespace boost typedef typename C::value_compare value_compare; typedef typename C::iterator iterator; -#if BOOST_WORKAROUND(__GNUC__, <= 3) - AssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~AssociativeContainer() + BOOST_CONCEPT_USAGE(AssociativeContainer) { i = c.find(k); r = c.equal_range(k); @@ -1025,10 +871,7 @@ namespace boost BOOST_concept(UniqueAssociativeContainer,(C)) : AssociativeContainer { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - UniqueAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~UniqueAssociativeContainer() + BOOST_CONCEPT_USAGE(UniqueAssociativeContainer) { C c(first, last); @@ -1046,10 +889,7 @@ namespace boost BOOST_concept(MultipleAssociativeContainer,(C)) : AssociativeContainer { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - MultipleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~MultipleAssociativeContainer() + BOOST_CONCEPT_USAGE(MultipleAssociativeContainer) { C c(first, last); @@ -1068,10 +908,7 @@ namespace boost BOOST_concept(SimpleAssociativeContainer,(C)) : AssociativeContainer { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - SimpleAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~SimpleAssociativeContainer() + BOOST_CONCEPT_USAGE(SimpleAssociativeContainer) { typedef typename C::key_type key_type; typedef typename C::value_type value_type; @@ -1082,10 +919,7 @@ namespace boost BOOST_concept(PairAssociativeContainer,(C)) : AssociativeContainer { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - PairAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~PairAssociativeContainer() + BOOST_CONCEPT_USAGE(PairAssociativeContainer) { typedef typename C::key_type key_type; typedef typename C::value_type value_type; @@ -1099,10 +933,7 @@ namespace boost : AssociativeContainer , ReversibleContainer { -#if BOOST_WORKAROUND(__GNUC__, <= 3) - SortedAssociativeContainer(); // at least 2.96 and 3.4.3 both need this :( -#endif - ~SortedAssociativeContainer() + BOOST_CONCEPT_USAGE(SortedAssociativeContainer) { C c(kc), diff --git a/prog_with_concepts.htm b/prog_with_concepts.htm index dd58d15..2aa9e22 100644 --- a/prog_with_concepts.htm +++ b/prog_with_concepts.htm @@ -1,57 +1,55 @@ - - - -Programming With Concepts - -C++ Boost + -
    + + + + + -

    Programming with Concepts

    + + -The process of deciding how to group requirements into concepts and -deciding which concepts to use in each algorithm is perhaps the most -difficult (yet most important) part of building a generic library. -A guiding principle to use during this process is one we -call the requirement minimization principle. + Programming With Concepts + + + -

    -Requirement Minimization Principle: Minimize the requirements -on the input parameters of a component to increase its reusability. + + C++ Boost
    -

    -There is natural tension in this statement. By definition, the input -parameters must be used by the component in order for the component to -accomplish its task (by ``component'' we mean a function or class -template). The challenge then is to implement the component in such a -way that makes the fewest assumptions (the minimum requirements) about -the inputs while still accomplishing the task. +

    Programming with Concepts

    -

    -The traditional notions of abstraction tie in directly to the -idea of minimal requirements. The more abstract the input, the fewer -the requirements. Thus, concepts are simply the embodiment of generic -abstract data types in C++ template programming. +

    The process of deciding how to group requirements into concepts and + deciding which concepts to use in each algorithm is perhaps the most + difficult (yet most important) part of building a generic library. A + guiding principle to use during this process is one we call the + requirement minimization principle.

    -

    -When designing the concepts for some problem domain it is important to -keep in mind their purpose, namely to express the requirements for the -input to the components. With respect to the requirement minimization -principle, this means we want to minimize concepts. +

    Requirement Minimization Principle: Minimize the requirements on + the input parameters of a component to increase its reusability.

    - +-->

    -

    -Minimality in concepts is a property associated with the underlying -semantics of the problem domain being represented. In the problem -domain of basic containers, requiring traversal in a single direction -is a smaller requirement than requiring traversal in both directions -(hence the distinction between -ForwardIterator and - -BidirectionalIterator). The semantic difference can be easily seen -in the difference between the set of concrete data structures that -have forward iterators versus the set that has bidirectional -iterators. For example, singly-linked lists would fall in the set of -data structures having forward iterators, but not bidirectional -iterators. In addition, the set of algorithms that one can implement -using only forward iterators is quite different than the set that can -be implemented with bidirectional iterators. Because of this, it is -important to factor families of requirements into rather fine-grained -concepts. For example, the requirements for iterators are factored -into the six STL iterator concepts (trivial, output, input, forward, -bidirectional, and random access). +

    Minimality in concepts is a property associated with the underlying + semantics of the problem domain being represented. In the problem domain of + basic containers, requiring traversal in a single direction is a smaller + requirement than requiring traversal in both directions (hence the + distinction between ForwardIterator and + BidirectionalIterator). + The semantic difference can be easily seen in the difference between the + set of concrete data structures that have forward iterators versus the set + that has bidirectional iterators. For example, singly-linked lists would + fall in the set of data structures having forward iterators, but not + bidirectional iterators. In addition, the set of algorithms that one can + implement using only forward iterators is quite different than the set that + can be implemented with bidirectional iterators. Because of this, it is + important to factor families of requirements into rather fine-grained + concepts. For example, the requirements for iterators are factored into the + six STL iterator concepts (trivial, output, input, forward, bidirectional, + and random access).

    -

    -Next: Implementation
    -Prev: Concept Covering and Archetypes +

    Next: Implementation
    + Prev: Concept Covering and + Archetypes

    +
    -
    -
    - - -
    Copyright © 2000 -Jeremy Siek(jsiek@osl.iu.edu) -Andrew Lumsdaine(lums@osl.iu.edu) -
    + + + - - + +
    Copyright © 2000Jeremy Siek(jsiek@osl.iu.edu) Andrew + Lumsdaine(lums@osl.iu.edu), + 2007 David Abrahams. +
    + + diff --git a/reference.htm b/reference.htm index d99909f..f5dd9d9 100644 --- a/reference.htm +++ b/reference.htm @@ -1,308 +1,391 @@ - - - -Boost Concept Checking Reference - - -C++ Boost + -
    + + + + + -

    Reference

    + + + + -
      -
    1. Functions
    2. -
    3. Macros
    4. -
    5. Basic Concept Checking Classes
    6. -
    7. Iterator Concept Checking Classes
    8. -
    9. Function Object Concept Checking Classes
    10. -
    11. Container Concept Checking Classes
    12. -
    13. Basic Archetype Classes
    14. -
    15. Iterator Archetype Classes
    16. -
    17. Function Object Archetype Classes
    18. -
    19. Container Archetype Classes
    20. -
    + Boost Concept Checking Reference + -

    Functions

    + + C++ Boost
    -
    -  template <class Concept>
    -  void function_requires();
    +  

    Reference

    + +
      +
    1. Macros
    2. + +
    3. Basic Concept Checking Classes
    4. + +
    5. Iterator Concept Checking + Classes
    6. + +
    7. Function Object Concept Checking + Classes
    8. + +
    9. Container Concept Checking + Classes
    10. + +
    11. Basic Archetype Classes
    12. + +
    13. Iterator Archetype Classes
    14. + +
    15. Function Object Archetype + Classes
    16. + +
    17. Container Archetype Classes
    18. + +
    19. Deprecated Functions
    20. + +
    21. Deprecated Macros
    22. + +
    23. Deprecated Concept + Checking Classes
    24. +
    + +

    Macros

    +
    +#include "boost/concept/assert.hpp"
    +
    +BOOST_CONCEPT_ASSERT((concept checking class template specialization));
     
    -

    Macros

    +

    Effects: causes a compilation failure if the concept is + not satisfied.
    + Note: this macro can be used at global, class, or function + scope.

    -
    -  // Apply concept checks in class definitions.
    -  BOOST_CLASS_REQUIRE(type, namespace-of-concept, concept);
    -  BOOST_CLASS_REQUIRE2(type1, type2, namespace-of-concept, concept);
    -  BOOST_CLASS_REQUIRE3(type1, type2, type3, namespace-of-concept, concept);
    -  BOOST_CLASS_REQUIRE4(type1, type2, type3, type4, namespace-of-concept, concept);
    +  

    Basic Concept Checking + Classes

    +
    +#include "boost/concept_check.hpp"
    +
    +template <class T>
    +struct Integer; // Is T a built-in integer type?
    +
    +template <class T>
    +struct SignedInteger; // Is T a built-in signed integer type?
    +
    +template <class T>
    +struct UnsignedInteger; // Is T a built-in unsigned integer type?
    +
    +template <class X, class Y>
    +struct Convertible; // Is X convertible to Y?
    +
    +template <class T>
    +struct Assignable; // Standard ref 23.1
    +
    +template <class T>
    +struct SGIAssignable;
    +
    +template <class T>
    +struct DefaultConstructible;
    +
    +template <class T> 
    +struct CopyConstructible; // Standard ref 20.1.3
    +
    +template <class T> 
    +struct EqualityComparable; // Standard ref 20.1.1
    +
    +template <class T>
    +struct LessThanComparable; // Standard ref 20.1.2
    +
    +template <class T>
    +struct Comparable; // The SGI STL LessThanComparable concept
     
    -Deprecated macros: +

    Iterator Concept + Checking Classes

    +
    +template <class Iter>
    +struct InputIterator; // Standard ref 24.1.1 Table 72
     
    -
    -  // Apply concept checks in class definitions.
    -  BOOST_CLASS_REQUIRES(type, concept);
    -  BOOST_CLASS_REQUIRES2(type1, type2, concept);
    -  BOOST_CLASS_REQUIRES3(type1, type2, type3, concept);
    -  BOOST_CLASS_REQUIRES4(type1, type2, type3, type4, concept);
    +template <class Iter, class T> 
    +struct OutputIterator; // Standard ref 24.1.2 Table 73
    +
    +template <class Iter> 
    +struct ForwardIterator; // Standard ref 24.1.3 Table 74
    +
    +template <class Iter> 
    +struct Mutable_ForwardIterator;
    +
    +template <class Iter> 
    +struct BidirectionalIterator; // Standard ref 24.1.4 Table 75
    +
    +template <class Iter> 
    +struct Mutable_BidirectionalIterator;
    +
    +template <class Iter> 
    +struct RandomAccessIterator; // Standard ref 24.1.5 Table 76
    +
    +template <class Iter> 
    +struct Mutable_RandomAccessIterator;
     
    -

    Basic Concept Checking Classes

    +

    Function Object Concept Checking + Classes

    +
    +#include "boost/concept_check.hpp"
     
    -
    -  template <class T>
    -  struct IntegerConcept; // Is T a built-in integer type?
    +template <class Func, class Return>
    +struct Generator;
     
    -  template <class T>
    -  struct SignedIntegerConcept; // Is T a built-in signed integer type?
    +template <class Func, class Return, class Arg>
    +struct UnaryFunction;
     
    -  template <class T>
    -  struct UnsignedIntegerConcept; // Is T a built-in unsigned integer type?
    +template <class Func, class Return, class First, class Second>
    +struct BinaryFunction;
     
    -  template <class X, class Y>
    -  struct ConvertibleConcept; // Is X convertible to Y?
    +template <class Func, class Arg>
    +struct UnaryPredicate;
     
    -  template <class T>
    -  struct AssignableConcept; // Standard ref 23.1
    +template <class Func, class First, class Second>
    +struct BinaryPredicate;
     
    -  template <class T>
    -  struct SGIAssignableConcept;
    +template <class Func, class First, class Second>
    +struct Const_BinaryPredicate;
     
    -  template <class T>
    -  struct DefaultConstructibleConcept;
    +template <class Func, class Return>
    +struct AdaptableGenerator;
     
    -  template <class T> 
    -  struct CopyConstructibleConcept; // Standard ref 20.1.3
    +template <class Func, class Return, class Arg>
    +struct AdaptableUnaryFunction;
     
    -  template <class T> 
    -  struct EqualityComparableConcept; // Standard ref 20.1.1
    +template <class Func, class First, class Second>
    +struct AdaptableBinaryFunction;
     
    -  template <class T>
    -  struct LessThanComparableConcept; // Standard ref 20.1.2
    +template <class Func, class Arg>
    +struct AdaptablePredicate;
     
    -  template <class T>
    -  struct ComparableConcept; // The SGI STL LessThanComparable concept
    +template <class Func, class First, class Second>
    +struct AdaptableBinaryPredicate;
     
    -

    Iterator Concept Checking Classes

    +

    Container Concept + Checking Classes

    +
    +#include "boost/concept_check.hpp"
     
    -
    -  template <class Iter>
    -  struct InputIteratorConcept; // Standard ref 24.1.1 Table 72
    +template <class C>
    +struct Container; // Standard ref 23.1 Table 65
     
    -  template <class Iter, class T> 
    -  struct OutputIteratorConcept; // Standard ref 24.1.2 Table 73
    +template <class C>
    +struct Mutable_Container;
     
    -  template <class Iter> 
    -  struct ForwardIteratorConcept; // Standard ref 24.1.3 Table 74
    +template <class C>
    +struct ForwardContainer;
     
    -  template <class Iter> 
    -  struct Mutable_ForwardIteratorConcept;
    +template <class C>
    +struct Mutable_ForwardContainer;
     
    -  template <class Iter> 
    -  struct BidirectionalIteratorConcept; // Standard ref 24.1.4 Table 75
    +template <class C>
    +struct ReversibleContainer; // Standard ref 23.1 Table 66
     
    -  template <class Iter> 
    -  struct Mutable_BidirectionalIteratorConcept;
    +template <class C>
    +struct Mutable_ReversibleContainer;
     
    -  template <class Iter> 
    -  struct RandomAccessIteratorConcept; // Standard ref 24.1.5 Table 76
    +template <class C>
    +struct RandomAccessContainer;
     
    -  template <class Iter> 
    -  struct Mutable_RandomAccessIteratorConcept;
    +template <class C>
    +struct Mutable_RandomAccessContainer;
    +
    +template <class C>
    +struct Sequence; // Standard ref 23.1.1
    +
    +template <class C>
    +struct FrontInsertionSequence;
    +
    +template <class C>
    +struct BackInsertionSequence;
    +
    +template <class C>
    +struct AssociativeContainer; // Standard ref 23.1.2 Table 69
    +
    +template <class C>
    +struct UniqueAssociativeContainer;
    +
    +template <class C>
    +struct MultipleAssociativeContainer;
    +
    +template <class C>
    +struct SimpleAssociativeContainer;
    +
    +template <class C>
    +struct PairAssociativeContainer;
    +
    +template <class C>
    +struct SortedAssociativeContainer;
     
    -

    Function Object Concept Checking Classes

    +

    Basic Archetype + Classes

    +
    +#include "boost/concept_archetype.hpp"
     
    -
    -  template <class Func, class Return>
    -  struct GeneratorConcept;
    +template <class T = int>
    +class null_archetype; // A type that models no concepts.
     
    -  template <class Func, class Return, class Arg>
    -  struct UnaryFunctionConcept;
    +template <class Base = null_archetype>
    +class default_constructible_archetype;
     
    -  template <class Func, class Return, class First, class Second>
    -  struct BinaryFunctionConcept;
    +template <class Base = null_archetype>
    +class assignable_archetype;
     
    -  template <class Func, class Arg>
    -  struct UnaryPredicateConcept;
    +template <class Base = null_archetype>
    +class copy_constructible_archetype;
     
    -  template <class Func, class First, class Second>
    -  struct BinaryPredicateConcept;
    +template <class Base = null_archetype>
    +class equality_comparable_archetype;
     
    -  template <class Func, class First, class Second>
    -  struct Const_BinaryPredicateConcept;
    -
    -  template <class Func, class Return>
    -  struct AdaptableGeneratorConcept;
    -
    -  template <class Func, class Return, class Arg>
    -  struct AdaptableUnaryFunctionConcept;
    -
    -  template <class Func, class First, class Second>
    -  struct AdaptableBinaryFunctionConcept;
    -
    -  template <class Func, class Arg>
    -  struct AdaptablePredicateConcept;
    -
    -  template <class Func, class First, class Second>
    -  struct AdaptableBinaryPredicateConcept;
    -  
    +template <class T, class Base = null_archetype>
    +class convertible_to_archetype;
     
    -

    Container Concept Checking Classes

    +

    Iterator Archetype + Classes

    +
    +#include "boost/concept_archetype.hpp"
     
    -
    -  template <class C>
    -  struct ContainerConcept; // Standard ref 23.1 Table 65
    +template <class ValueType>
    +class trivial_iterator_archetype;
     
    -  template <class C>
    -  struct Mutable_ContainerConcept;
    +template <class ValueType>
    +class mutable_trivial_iterator_archetype;
     
    -  template <class C>
    -  struct ForwardContainerConcept;
    +template <class ValueType>
    +class input_iterator_archetype;
     
    -  template <class C>
    -  struct Mutable_ForwardContainerConcept;
    +template <class ValueType>
    +class forward_iterator_archetype;
     
    -  template <class C>
    -  struct ReversibleContainerConcept; // Standard ref 23.1 Table 66
    +template <class ValueType>
    +class bidirectional_iterator_archetype;
     
    -  template <class C>
    -  struct Mutable_ReversibleContainerConcept;
    -
    -  template <class C>
    -  struct RandomAccessContainerConcept;
    -
    -  template <class C>
    -  struct Mutable_RandomAccessContainerConcept;
    -
    -  template <class C>
    -  struct SequenceConcept; // Standard ref 23.1.1
    -
    -  template <class C>
    -  struct FrontInsertionSequenceConcept;
    -
    -  template <class C>
    -  struct BackInsertionSequenceConcept;
    -
    -  template <class C>
    -  struct AssociativeContainerConcept; // Standard ref 23.1.2 Table 69
    -
    -  template <class C>
    -  struct UniqueAssociativeContainerConcept;
    -
    -  template <class C>
    -  struct MultipleAssociativeContainerConcept;
    -
    -  template <class C>
    -  struct SimpleAssociativeContainerConcept;
    -
    -  template <class C>
    -  struct PairAssociativeContainerConcept;
    -
    -  template <class C>
    -  struct SortedAssociativeContainerConcept;
    +template <class ValueType>
    +class random_access_iterator_archetype;
     
    +

    Function Object Archetype Classes

    +
    +#include "boost/concept_archetype.hpp"
     
    -

    Basic Archetype Classes

    +template <class Arg, class Return> +class unary_function_archetype; -
    -  template <class T = int>
    -  class null_archetype; // A type that models no concepts.
    +template <class Arg1, class Arg2, class Return>
    +class binary_function_archetype;
     
    -  template <class Base = null_archetype>
    -  class default_constructible_archetype;
    +template <class Arg>
    +class predicate_archetype;
     
    -  template <class Base = null_archetype>
    -  class assignable_archetype;
    -
    -  template <class Base = null_archetype>
    -  class copy_constructible_archetype;
    -
    -  template <class Base = null_archetype>
    -  class equality_comparable_archetype;
    -
    -  template <class T, class Base = null_archetype>
    -  class convertible_to_archetype;
    +template <class Arg1, class Arg2>
    +class binary_predicate_archetype;
     
    -

    Iterator Archetype Classes

    - -
    -  template <class ValueType>
    -  class trivial_iterator_archetype;
    -
    -  template <class ValueType>
    -  class mutable_trivial_iterator_archetype;
    -
    -  template <class ValueType>
    -  class input_iterator_archetype;
    -
    -  template <class ValueType>
    -  class forward_iterator_archetype;
    -
    -  template <class ValueType>
    -  class bidirectional_iterator_archetype;
    -
    -  template <class ValueType>
    -  class random_access_iterator_archetype;
    -
    -
    - -

    Function Object Archetype Classes

    - -
    -  template <class Arg, class Return>
    -  class unary_function_archetype;
    -
    -  template <class Arg1, class Arg2, class Return>
    -  class binary_function_archetype;
    -
    -  template <class Arg>
    -  class predicate_archetype;
    -
    -  template <class Arg1, class Arg2>
    -  class binary_predicate_archetype;
    -
    - -

    Container Archetype Classes

    - -
    +  

    Container + Archetype Classes

    +
     UNDER CONSTRUCTION
     
    -

    -Back to Introduction -
    -Prev: Implementation +

    Deprecated + Functions

    +
    +#include "boost/concept_check.hpp"
     
    -
    -
    - - -
    Copyright © 2000 -Jeremy Siek(jsiek@osl.iu.edu) -Andrew Lumsdaine(lums@osl.iu.edu) -
    +template <class Concept> +void function_requires(); +
    - - +

    Deprecated + Macros

    +
    +#include "boost/concept_check.hpp"
    +
    +// Apply concept checks in class definitions.
    +BOOST_CLASS_REQUIRE(type, namespace-of-concept, concept);
    +BOOST_CLASS_REQUIRE2(type1, type2, namespace-of-concept, concept);
    +BOOST_CLASS_REQUIRE3(type1, type2, type3, namespace-of-concept, concept);
    +BOOST_CLASS_REQUIRE4(type1, type2, type3, type4, namespace-of-concept, concept);
    +
    +// Apply concept checks in class definitions.
    +BOOST_CLASS_REQUIRES(type, concept);
    +BOOST_CLASS_REQUIRES2(type1, type2, concept);
    +BOOST_CLASS_REQUIRES3(type1, type2, type3, concept);
    +BOOST_CLASS_REQUIRES4(type1, type2, type3, type4, concept);
    +
    + +

    Deprecated Concept Checking + Classes

    + +

    For each of the concepts documented here, the library includes an + identical concept checking class whose name ends in + “Concept” For example, in + addition to RandomAccessIterator, the library defines a + RandomAccessIteratorConcept class template.

    + +

    Back to Introduction
    + Prev: Implementation

    +
    + + + + + + + +
    Copyright © 2000Jeremy Siek(jsiek@osl.iu.edu) Andrew + Lumsdaine(lums@osl.iu.edu), 2007 + David Abrahams.
    + + diff --git a/using_concept_check.htm b/using_concept_check.htm index ff120f8..3dc311d 100644 --- a/using_concept_check.htm +++ b/using_concept_check.htm @@ -1,227 +1,186 @@ - - - -Using Concept Checks - -C++ Boost + -
    + + + + + + + + -

    Using Concept Checks

    + Using Concept Checks + + -For each concept there is a concept checking class which can be used -to make sure that a given type (or set of types) models the concept. -The Boost Concept Checking Library (BCCL) includes concept checking classes -for all of the concepts used in the C++ standard library and a few -more. The Reference section lists these -concept checking classes. In addition, other boost libraries come with -concept checking classes for the concepts that are particular to those -libraries. For example, there are graph concepts and property map concepts. -Also, whenever anyone writing a class of function template -needs to express requirements that are not yet stated by an existing -concept, a new concept checking class should be created. How -to do this is explained in Creating -Concept Checking Classes. + + C++ Boost
    -

    -An example of a concept checking class from the BCCL is the -EqualityComparableConcept class. The class corresponds to the -EqualityComparable requirements described in 20.1.1 of the C++ -Standard, and to the EqualityComparable -concept documented in the SGI STL. +

    Using Concept + Checks

    -
    -  template <class T>
    -  struct EqualityComparableConcept;
    +  

    For each concept there is a concept checking class template that can be + used to make sure that a given type (or set of types) models the concept. + The Boost Concept Checking Library (BCCL) includes concept checking class + templates for all of the concepts used in the C++ standard library and a + few more. See the Reference section for a + complete list. In addition, other boost libraries come with concept + checking classes for the concepts that are particular to those libraries. + For example, there are graph + concepts and property map + concepts. Also, whenever anyone writing function templates needs + to express requirements that are not yet stated by an existing concept, a + new concept checking class should be created. How to do this is explained + in Creating Concept Checking + Classes.

    + +

    An example of a concept checking class from the BCCL is the + EqualityComparableConcept class. The class corresponds to the + EqualityComparable requirements described in 20.1.1 of the C++ Standard, + and to the EqualityComparable + concept documented in the SGI STL.

    +
    +template <class T>
    +struct EqualityComparable;
     
    -The template argument T will the type to be checked. That is, -the purpose of EqualityComparableConcept is to make sure that -the template argument given for T models the -EqualityComparable concept. +

    The template argument is the type to be checked. That is, the purpose of + EqualityComparable<X> is to make sure that + X models the EqualityComparable concept.

    -

    -Each concept checking class has a member function named -constraints() which contains the valid expressions for the -concept. To check whether some type is EqualityComparable we need to -instantiate the concept checking class with the type and then find a -way to get the compiler to compile the constraints() function -without actually executing the function. The Boost Concept Checking -Library defines two utilities that make this easy: -function_requires() and BOOST_CLASS_REQUIRE. +

    BOOST_CONCEPT_ASSERT()

    -

    function_requires()

    +

    The most versatile way of checking concept requirements is to use the + BOOST_CONCEPT_ASSERT() macro. You can use this macro at any + scope, by passing a concept checking template specialization enclosed in + parentheses. Note: that means invocations of + BOOST_CONCEPT_ASSERT will appear to use double + parentheses.

    +
    +// In my library:
    +template <class T>
    +void generic_library_function(T x)
    +{
    +  BOOST_CONCEPT_ASSERT((EqualityComparable<T>));
    +  // ...
    +};
     
    -The function_requires() function can be used in function bodies
    -and the BOOST_CLASS_REQUIRE macro can be used inside class
    -bodies. The function_requires() function takes no arguments,
    -but has a template parameter for the concept checking class. This
    -means that the instantiated concept checking class must be given as an
    -explicit template argument, as shown below.
    +template <class It>
    +class generic_library_class
    +{
    +  BOOST_CONCEPT_ASSERT((RandomAccessIterator<It>));
    +  // ...
    +};
     
    -
    -  // In my library:
    -  template <class T>
    -  void generic_library_function(T x)
    -  {
    -    function_requires< EqualityComparableConcept<T> >();
    -    // ...
    -  };
    +// In the user's code:  
    +class foo {
    +  //... 
    +};
     
    -  // In the user's code:  
    -  class foo {
    -    //... 
    -  };
    -
    -  int main() {
    -    foo f;
    -    generic_library_function(f);
    -    return 0;
    -  }
    +int main() {
    +  foo x;
    +  generic_library_function(x);
    +  generic_library_class<std::vector<char>::iterator> y;
    +  //... 
    +}
     
    +

    BOOST_CONCEPT_REQUIRES

    -

    BOOST_CLASS_REQUIRE

    +

    One of the nice things about the proposed C++0x syntax + for declaring concept constrained function templates is the way that + constraints are part of the function declaration, so clients will + see them. BOOST_CONCEPT_ASSERT can only express constraints + within the function template definition, which hides the constraint in the + function body. Aside from the loss of a self-documenting interface, + asserting conformance only in the function body can undesirably delay + checking if the function is explicitly instantiated in a different + translation unit from the one in which it is called, or if the compiler + does link-time instantiation.

    -The BOOST_CLASS_REQUIRE macro can be used inside a class -definition to check whether some type models a concept. Make sure -that the arguments to this macro are simply identifiers. You may need -to use typedef to get your types into this form. - -
    -  // In my library:
    -  template <class T>
    -  struct generic_library_class
    -  {
    -    BOOST_CLASS_REQUIRE(T, boost, EqualityComparableConcept);
    -    // ...
    -  };
    -
    -  // In the user's code:  
    -  class foo {
    -    //... 
    -  };
    -
    -  int main() {
    -    generic_library_class<foo> glc;
    -    // ...
    -    return 0;
    -  }
    +  

    The BOOST_CONCEPT_REQUIRES macro can be used in a function + template declaration to check whether some type models a concept. It + accepts two arguments, a list of constraints, and the + function template's return type. The list of constraints takes the form of + a sequence of adjacent concept checking template specializations, + in double parentheses, and the function's return type must + also be parenthesized. For example, the standard stable_sort + algorithm might be declared as follows: class

    +
    +template<typename RanIter>
    +BOOST_CONCEPT_REQUIRES(
    +    ((Mutable_RandomAccessIterator<RanIter>))
    +    ((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>)),
    +    (void)) // return type
    +    stable_sort(RanIter,RanIter);
     
    +

    Note that the algorithm requires that the value type of the iterator be + LessThanComparable, and it accesses that value type through the + Mutable_RandomAccessIterator concept checking template. In + general, the Boost concept checking classes expose associated types as + nested member typedefs so that you can use this syntax, which mimics the + approach used in the concept support proposed for the next version of + C++.

    -

    Example

    +

    Multi-Type Concepts

    -

    -Getting back to the earlier motivating example, -one good application of concept checks would be to insert -function_requires() at the top of std::stable_sort() -to make sure the template parameter type models -RandomAccessIterator. In addition, std::stable_sort() -requires that the value_type of the iterators be - -LessThanComparable, so we also use function_requires() to -check this. - -

    -  template <class RandomAccessIter>
    -  void stable_sort(RandomAccessIter first, RandomAccessIter last)
    -  {
    -    function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
    -    typedef typename std::iterator_traits<RandomAccessIter>::value_type value_type;
    -    function_requires< LessThanComparableConcept<value_type> >();
    -    ...
    -  }
    +  

    Some concepts deal with more than one type. In this case the + corresponding concept checking class will have multiple template + parameters. The following example shows how BOOST_CONCEPT_REQUIRES + is used with the ReadWritePropertyMap + concept, which takes two type parameters: a property map and the key type + for the map.

    +
    +template <class G, class Buffer, class BFSVisitor, 
    +          class ColorMap>
    +BOOST_CONCEPT_REQUIRES(
    +  ((ReadWritePropertyMap<ColorMap, typename IncidenceGraph<G>::vertex_descriptor>)),
    +  (void)) // return type
    +breadth_first_search(G& g, 
    +  typename graph_traits<IncidenceGraph>::vertex_descriptor s, 
    +  Buffer& Q, BFSVisitor vis, ColorMap color)
    +{
    +  typedef typename IncidenceGraph<G>::vertex_descriptor Vertex;
    +  ...
    +}
     
    - - - - -

    -Some concepts deal with more than one type. In this case the -corresponding concept checking class will have multiple template -parameters. The following example shows how -function_requires() is used with the ReadWritePropertyMap -concept which takes two type parameters: a property map and the key -type for the map. - -

    -  template <class IncidenceGraph, class Buffer, class BFSVisitor, 
    -            class ColorMap>
    -  void breadth_first_search(IncidenceGraph& g, 
    -    typename graph_traits<IncidenceGraph>::vertex_descriptor s, 
    -    Buffer& Q, BFSVisitor vis, ColorMap color)
    -  {
    -    typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
    -    function_requires< ReadWritePropertyMap<ColorMap, Vertex> >();
    -    ...
    -  }
    +  

    Although concept checks are designed for use by generic library + implementors, they can also be useful to end users. Sometimes one may not + be sure whether some type models a particular concept. The syntactic + requirements, at least, can easily be checked by creating a small program + and using BOOST_CONCEPT_ASSERT with the type and concept in + question. For example:

    +
    +// Make sure list<int> has bidirectional iterators.
    +BOOST_CONCEPT_ASSERT((BidirectionalIterator<std::list<int>::iterator>));
     
    +

    Prev: Concept Checking + Introduction
    + Next: Creating Concept Checking + Classes

    +
    -As an example of using BOOST_CLASS_REQUIRE we look at a concept -check that could be added to std::vector. One requirement -that is placed on the element type is that it must be Assignable. -We can check this by inserting -class_requires<AssignableConcept<T> > at the top -of the definition for std::vector. + + + -
    -  namespace std {
    -    template <class T>
    -    struct vector {
    -      BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
    -      ...
    -    };
    -  }
    -
    - - -Although the concept checks are designed for use by generic library -implementors, they can also be useful to end users. Sometimes one may -not be sure whether some type models a particular concept. This can -easily be checked by creating a small program and using -function_requires() with the type and concept in question. -The file stl_concept_checks.cpp -gives and example of applying the concept checks to STL containers. - -

    -Prev: Concept Checking Introduction
    -Next: Creating Concept Checking Classes - -
    -


    -
    Copyright © 2000
    - -
    Copyright © 2000 -Jeremy Siek(jsiek@osl.iu.edu) -Andrew Lumsdaine(lums@osl.iu.edu) -
    - - - + Jeremy Siek(jsiek@osl.iu.edu) Andrew + Lumsdaine(lums@osl.iu.edu), 2007 + David Abrahams. + + + + From d9ae9769943533e1e9d8217a17a92c91bdb8eb9f Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 5 Nov 2007 04:43:31 +0000 Subject: [PATCH 25/25] Moved boost/concept/where.hpp to boost/concept/requires.hpp Updated reference.htm to include BOOST_CONCEPT_REQUIRES Fixed a copyright notice. [SVN r40770] --- bibliography.htm | 17 +++++------------ fake_sort.hpp | 2 +- .../boost/concept/{where.hpp => requires.hpp} | 0 reference.htm | 17 +++++++++++++++++ 4 files changed, 23 insertions(+), 13 deletions(-) rename include/boost/concept/{where.hpp => requires.hpp} (100%) diff --git a/bibliography.htm b/bibliography.htm index 267f6c1..2c42925 100644 --- a/bibliography.htm +++ b/bibliography.htm @@ -1,17 +1,10 @@ - + + + + -Boost Graph Library: Bibliography +Boost Concept Checking Library: Bibliography -# include +# include # include namespace fake diff --git a/include/boost/concept/where.hpp b/include/boost/concept/requires.hpp similarity index 100% rename from include/boost/concept/where.hpp rename to include/boost/concept/requires.hpp diff --git a/reference.htm b/reference.htm index f5dd9d9..0e1797b 100644 --- a/reference.htm +++ b/reference.htm @@ -66,6 +66,23 @@ BOOST_CONCEPT_ASSERT((concept checking class template specialization)); Note: this macro can be used at global, class, or function scope.

    +
    +#include "boost/concept/requires.hpp"
    +
    +template <…template parameters…>
    +BOOST_CONCEPT_REQUIRES(
    +  ((concept checking class template specialization1)) 
    +  ((concept checking class template specialization2))… 
    +  ((concept checking class template specializationn)),
    +  (function return type)
    +) function_template_name(…function parameters…)
    +
    + +

    Effects: causes a compilation failure if the + given concepts are not satisfied.
    + Note: this macro is intended to be used in place of + a function template's return type.

    +

    Basic Concept Checking Classes