diff --git a/include/boost/concept_archetype.hpp b/include/boost/concept_archetype.hpp new file mode 100644 index 0000000..994e149 --- /dev/null +++ b/include/boost/concept_archetype.hpp @@ -0,0 +1,599 @@ +// +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +// +#ifndef BOOST_CONCEPT_ARCHETYPES_HPP +#define BOOST_CONCEPT_ARCHETYPES_HPP + +#include +#include + +namespace boost { + + //=========================================================================== + // Basic Archetype Classes + + namespace detail { + class dummy_constructor { }; + } + static detail::dummy_constructor dummy_cons; + + // A type that models no concept. The template parameter + // is only there so that null_archetype types can be created + // that have different type. + template + class null_archetype { + private: + null_archetype() { } + null_archetype(const null_archetype&) { } + null_archetype& operator=(const null_archetype&) { return *this; } + public: + null_archetype(detail::dummy_constructor) { } + template + friend void dummy_friend(); // just to avoid warnings + }; + + // This is a helper class that provides a way to get a reference to + // an object. + template + class static_object { + public: + static T& get() { + detail::dummy_constructor d; + static T x(d); + return x; + } + }; + template <> + class static_object { + public: + static bool& get() { + static bool b; + return b; + } + }; + template <> + class static_object { + public: + static int& get() { + static int b; + return b; + } + }; + + template > + class default_constructible_archetype : public Base { + public: + default_constructible_archetype() : Base(dummy_cons) { } + default_constructible_archetype(detail::dummy_constructor x) : Base(x) { } + }; + + template > + class assignable_archetype : public Base { + assignable_archetype() { } + assignable_archetype(const assignable_archetype&) { } + public: + assignable_archetype& operator=(const assignable_archetype&) { + return *this; + } + assignable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + + template > + class copy_constructible_archetype : public Base { + public: + copy_constructible_archetype() : Base(dummy_cons) { } + copy_constructible_archetype(const copy_constructible_archetype&) + : Base(dummy_cons) { } + copy_constructible_archetype(detail::dummy_constructor x) : Base(x) { } + }; + + template > + class sgi_assignable_archetype : public Base { + public: + sgi_assignable_archetype(const sgi_assignable_archetype&) + : Base(dummy_cons) { } + sgi_assignable_archetype& operator=(const sgi_assignable_archetype&) { + return *this; + } + sgi_assignable_archetype(const detail::dummy_constructor& x) : Base(x) { } + }; + + struct default_archetype_base { + default_archetype_base(detail::dummy_constructor x) { } + }; + + // Careful, don't use same type for T and Base. That results in the + // conversion operator being invalid. Since T is often + // null_archetype, can't use null_archetype for Base. + template + class convertible_to_archetype : public Base { + private: + convertible_to_archetype() { } + convertible_to_archetype(const convertible_to_archetype& ) { } + convertible_to_archetype& operator=(const convertible_to_archetype&) + { return *this; } + public: + convertible_to_archetype(detail::dummy_constructor x) : Base(x) { } + operator const T&() const { return static_object::get(); } + }; + + template + class convertible_from_archetype : public Base { + private: + convertible_from_archetype() { } + convertible_from_archetype(const convertible_from_archetype& ) { } + convertible_from_archetype& operator=(const convertible_from_archetype&) + { return *this; } + public: + convertible_from_archetype(detail::dummy_constructor x) : Base(x) { } + convertible_from_archetype(const T&) { } + convertible_from_archetype& operator=(const T&) + { return *this; } + }; + + class boolean_archetype { + public: + boolean_archetype(const boolean_archetype&) { } + operator bool() const { return true; } + boolean_archetype(detail::dummy_constructor x) { } + private: + boolean_archetype() { } + boolean_archetype& operator=(const boolean_archetype&) { return *this; } + }; + + template > + class equality_comparable_archetype : public Base { + public: + equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + template + boolean_archetype + operator==(const equality_comparable_archetype&, + const equality_comparable_archetype&) + { return boolean_archetype(dummy_cons); } + template + boolean_archetype + operator!=(const equality_comparable_archetype&, + const equality_comparable_archetype&) + { return boolean_archetype(dummy_cons); } + + + template > + class equality_comparable2_first_archetype : public Base { + public: + equality_comparable2_first_archetype(detail::dummy_constructor x) + : Base(x) { } + }; + template > + class equality_comparable2_second_archetype : public Base { + public: + equality_comparable2_second_archetype(detail::dummy_constructor x) + : Base(x) { } + }; + template + boolean_archetype + operator==(const equality_comparable2_first_archetype&, + const equality_comparable2_second_archetype&) + { return boolean_archetype(dummy_cons); } + template + boolean_archetype + operator!=(const equality_comparable2_first_archetype&, + const equality_comparable2_second_archetype&) + { return boolean_archetype(dummy_cons); } + + + template > + class less_than_comparable_archetype : public Base { + public: + less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + template + boolean_archetype + operator<(const less_than_comparable_archetype&, + const less_than_comparable_archetype&) + { return boolean_archetype(dummy_cons); } + + + + template > + class comparable_archetype : public Base { + public: + comparable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + template + boolean_archetype + operator<(const comparable_archetype&, + const comparable_archetype&) + { return boolean_archetype(dummy_cons); } + template + boolean_archetype + operator<=(const comparable_archetype&, + const comparable_archetype&) + { return boolean_archetype(dummy_cons); } + template + boolean_archetype + operator>(const comparable_archetype&, + const comparable_archetype&) + { return boolean_archetype(dummy_cons); } + template + boolean_archetype + operator>=(const comparable_archetype&, + const comparable_archetype&) + { return boolean_archetype(dummy_cons); } + + + // The purpose of the optags is so that one can specify + // exactly which types the operator< is defined between. + // This is useful for allowing the operations: + // + // A a; B b; + // a < b + // b < a + // + // without also allowing the combinations: + // + // a < a + // b < b + // + struct optag1 { }; + struct optag2 { }; + struct optag3 { }; + +#define BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(OP, NAME) \ + template , class Tag = optag1 > \ + class NAME##_first_archetype : public Base { \ + public: \ + NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template , class Tag = optag1 > \ + class NAME##_second_archetype : public Base { \ + public: \ + NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template \ + boolean_archetype \ + operator OP (const NAME##_first_archetype&, \ + const NAME##_second_archetype&) \ + { \ + return boolean_archetype(dummy_cons); \ + } + + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(==, equal_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(!=, not_equal_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(<, less_than_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(<=, less_equal_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(>, greater_than_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(>=, greater_equal_op) + +#define BOOST_DEFINE_OPERATOR_ARCHETYPE(OP, NAME) \ + template > \ + class NAME##_archetype : public Base { \ + public: \ + NAME##_archetype(detail::dummy_constructor x) : Base(x) { } \ + NAME##_archetype(const NAME##_archetype&) \ + : Base(dummy_cons) { } \ + NAME##_archetype& operator=(const NAME##_archetype&) { return *this; } \ + }; \ + template \ + NAME##_archetype \ + operator OP (const NAME##_archetype&,\ + const NAME##_archetype&) \ + { return NAME##_archetype(dummy_cons); } + + BOOST_DEFINE_OPERATOR_ARCHETYPE(+, addable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(-, subtractable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(*, multipliable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(/, dividable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(%, modable) + + // As is, these are useless because of the return type. + // Need to invent a better way... +#define BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(OP, NAME) \ + template > \ + class NAME##_first_archetype : public Base { \ + public: \ + NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template > \ + class NAME##_second_archetype : public Base { \ + public: \ + NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template \ + Return \ + operator OP (const NAME##_first_archetype&, \ + const NAME##_second_archetype&) \ + { \ + return Return(dummy_cons); \ + } + + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(+, plus_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(*, time_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(/, divide_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(-, subtract_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(%, mod_op) + + //=========================================================================== + // Function Object Archetype Classes + + template + class generator_archetype { + public: + const Return& operator()() { + return static_object::get(); + } + }; + + class void_generator_archetype { + public: + void operator()() { } + }; + + template + class unary_function_archetype { + private: + unary_function_archetype() { } + public: + unary_function_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg&) { + return static_object::get(); + } + }; + + template + class binary_function_archetype { + private: + binary_function_archetype() { } + public: + binary_function_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg1&, const Arg2&) { + return static_object::get(); + } + }; + + template + class unary_predicate_archetype { + typedef boolean_archetype Return; + unary_predicate_archetype() { } + public: + unary_predicate_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg&) { + return static_object::get(); + } + }; + + template > + class binary_predicate_archetype { + typedef boolean_archetype Return; + binary_predicate_archetype() { } + public: + binary_predicate_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg1&, const Arg2&) { + return static_object::get(); + } + }; + + template + class const_binary_predicate_archetype { + typedef boolean_archetype Return; + const_binary_predicate_archetype() { } + public: + const_binary_predicate_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg1&, const Arg2&) const { + return static_object::get(); + } + }; + + + //=========================================================================== + // Iterator Archetype Classes + + template + struct input_proxy { + operator const T&() { return static_object::get(); } + }; + template + class trivial_iterator_archetype + { + typedef trivial_iterator_archetype self; + public: +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + typedef T value_type; + typedef void reference; + typedef void pointer; + typedef void difference_type; + typedef void iterator_category; +#endif + trivial_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + input_proxy operator*() const { return input_proxy(); } + }; +} // namespace boost + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace std { + template + struct iterator_traits< boost::trivial_iterator_archetype > + { + typedef T value_type; + }; +} +#endif + +namespace boost { + template + struct input_output_proxy { + input_output_proxy& operator=(const T&) { return *this; } + operator const T&() { return static_object::get(); } + }; + template + class mutable_trivial_iterator_archetype + { + typedef mutable_trivial_iterator_archetype self; + public: +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + typedef T value_type; + typedef void reference; + typedef void pointer; + typedef void difference_type; + typedef void iterator_category; +#endif + mutable_trivial_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + input_output_proxy operator*() const { return input_output_proxy(); } + }; +} // namespace boost + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace std { + template + struct iterator_traits< boost::mutable_trivial_iterator_archetype > + { + typedef T value_type; + }; +} +#endif + +namespace boost { + + template + class input_iterator_archetype + { + public: + typedef input_iterator_archetype self; + public: + typedef std::input_iterator_tag iterator_category; + typedef T value_type; + typedef const T& reference; + typedef const T* pointer; + typedef std::ptrdiff_t difference_type; + input_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + struct output_proxy { + output_proxy& operator=(const T&) { return *this; } + }; + + template + class output_iterator_archetype + { + public: + typedef output_iterator_archetype self; + public: + typedef std::output_iterator_tag iterator_category; + typedef output_proxy value_type; + typedef output_proxy reference; + typedef void pointer; + typedef void difference_type; + output_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return output_proxy(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + class forward_iterator_archetype + { + public: + typedef forward_iterator_archetype self; + public: + typedef std::forward_iterator_tag iterator_category; + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + forward_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + class bidirectional_iterator_archetype + { + public: + typedef bidirectional_iterator_archetype self; + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + bidirectional_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + self& operator--() { return *this; } + self operator--(int) { return *this; } + }; + + template + class random_access_iterator_archetype + { + public: + typedef random_access_iterator_archetype self; + public: + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + random_access_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + self& operator--() { return *this; } + self operator--(int) { return *this; } + reference operator[](difference_type n) + { return static_object::get(); } + self& operator+=(difference_type) { return *this; } + self& operator-=(difference_type) { return *this; } + difference_type operator-(const self&) const + { return difference_type(); } + self operator+(difference_type) { return *this; } + self operator-(difference_type) { return *this; } + bool operator<(const self&) { return true; } + bool operator<=(const self&) { return true; } + bool operator>(const self&) { return true; } + bool operator>=(const self&) { return true; } + }; + template + random_access_iterator_archetype + operator+(typename random_access_iterator_archetype::difference_type, + const random_access_iterator_archetype& x) + { return x; } + +} // namespace boost + +#endif // BOOST_CONCEPT_ARCHETYPES_H diff --git a/include/boost/concept_check.hpp b/include/boost/concept_check.hpp new file mode 100644 index 0000000..07edb53 --- /dev/null +++ b/include/boost/concept_check.hpp @@ -0,0 +1,942 @@ +// +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +// +#ifndef BOOST_CONCEPT_CHECKS_HPP +#define BOOST_CONCEPT_CHECKS_HPP + +#include +#include +#include +#include + +#if (__GNUC__) || defined(__KCC) || defined(__ghs) || defined(__MWERKS__) +#define BOOST_FPTR & +#else +#define BOOST_FPTR +#endif + +namespace boost { + +template void ignore_unused_variable_warning(const T&) { } + +template +void function_requires() +{ +#if !defined(NDEBUG) + void (Concept::*x)() = BOOST_FPTR Concept::constraints; + ignore_unused_variable_warning(x); +#endif +} + +// The BOOST_CLASS_REQUIRES macros use function pointers as +// template parameters, which VC++ does not support. + +#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 + + template + struct IntegerConcept { + void constraints() { +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + errortype_must_be_an_integer_type(); +#endif + } + }; +#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() {} }; + // etc. +#endif + + template + struct SignedIntegerConcept { + void constraints() { +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + errortype_must_be_a_signed_integer_type(); +#endif + } + }; +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template <> struct SignedIntegerConcept { void constraints() {} }; + template <> struct SignedIntegerConcept { void constraints() {} }; + template <> struct SignedIntegerConcept { void constraints() {} }; + // etc. +#endif + + template + struct UnsignedIntegerConcept { + void constraints() { +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + errortype_must_be_an_unsigned_integer_type(); +#endif + } + }; +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template <> struct UnsignedIntegerConcept + { void constraints() {} }; + template <> struct UnsignedIntegerConcept + { void constraints() {} }; + template <> struct UnsignedIntegerConcept + { void constraints() {} }; + // etc. +#endif + + //=========================================================================== + // Basic Concepts + + template + struct DefaultConstructibleConcept + { + void constraints() { + TT a; // require default constructor + ignore_unused_variable_warning(a); + } + }; + + template + struct AssignableConcept + { + void constraints() { +#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL + a = a; // require assignment operator +#endif + const_constraints(a); + } + 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; + }; + + template + struct CopyConstructibleConcept + { + void constraints() { + TT a(b); // require copy constructor + TT* ptr = &a; // require address of operator + const_constraints(a); + ignore_unused_variable_warning(ptr); + } + 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; + }; + + // The SGI STL version of Assignable requires copy constructor and operator= + template + struct SGIAssignableConcept + { + void constraints() { + TT b(a); +#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL + a = a; // require assignment operator +#endif + const_constraints(a); + } + void const_constraints(const TT& b) { + TT c(b); +#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL + a = b; // const required for argument to assignment +#endif + } + TT a; + }; + + template + struct ConvertibleConcept + { + void constraints() { + Y y = x; + ignore_unused_variable_warning(y); + } + X x; + }; + + // The C++ standard requirements for many concepts talk about return + // types that must be "convertible to bool". The problem with this + // requirement is that it leaves the door open for evil proxies that + // define things like operator|| with strange return types. Two + // possible solutions are: + // 1) require the return type to be exactly bool + // 2) stay with convertible to bool, and also + // specify stuff about all the logical operators. + // For now we just test for convertible to bool. + template + void require_boolean_expr(const TT& t) { + bool x = t; + ignore_unused_variable_warning(x); + } + + template + struct EqualityComparableConcept + { + void constraints() { + require_boolean_expr(a == b); + require_boolean_expr(a != b); + } + TT a, b; + }; + + template + struct LessThanComparableConcept + { + void constraints() { + require_boolean_expr(a < b); + } + TT a, b; + }; + + // This is equivalent to SGI STL's LessThanComparable. + template + struct ComparableConcept + { + void constraints() { + require_boolean_expr(a < b); + require_boolean_expr(a > b); + require_boolean_expr(a <= b); + require_boolean_expr(a >= b); + } + 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_OPERATOR_CONSTRAINT(OP,NAME) \ + template \ + struct NAME { \ + void constraints() { (void)constraints_(); } \ + 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_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); + + //=========================================================================== + // Function Object Concepts + + template + struct GeneratorConcept + { + void constraints() { + const Return& r = f(); // require operator() member function + } + Func f; + }; + + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct GeneratorConcept + { + void constraints() { + f(); // require operator() member function + } + Func f; + }; +#endif + + template + struct UnaryFunctionConcept + { + void constraints() { + r = f(arg); // require operator() + } + Func f; + Arg arg; + Return r; + }; + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct UnaryFunctionConcept { + void constraints() { + f(arg); // require operator() + } + Func f; + }; +#endif + + template + struct BinaryFunctionConcept + { + void constraints() { + r = f(first, second); // require operator() + } + Func f; + First first; + Second second; + Return r; + }; + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct BinaryFunctionConcept + { + void constraints() { + f(first, second); // require operator() + } + Func f; + First first; + Second second; + }; +#endif + + template + struct UnaryPredicateConcept + { + void constraints() { + require_boolean_expr(f(arg)); // require operator() returning bool + } + Func f; + Arg arg; + }; + + template + struct BinaryPredicateConcept + { + void constraints() { + require_boolean_expr(f(a, b)); // require operator() returning bool + } + Func f; + First a; + Second b; + }; + + // use this when functor is used inside a container class like std::set + template + struct Const_BinaryPredicateConcept { + void constraints() { + const_constraints(f); + } + 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; + }; + + //=========================================================================== + // Iterator Concepts + + template + struct TrivialIteratorConcept + { + void constraints() { + function_requires< AssignableConcept >(); + function_requires< DefaultConstructibleConcept >(); + function_requires< EqualityComparableConcept >(); +#ifndef BOOST_NO_STD_ITERATOR_TRAITS + typedef typename std::iterator_traits::value_type V; +#endif + (void)*i; // require dereference operator + } + TT i; + }; + + template + struct Mutable_TrivialIteratorConcept + { + void constraints() { + function_requires< TrivialIteratorConcept >(); + *i = *j; // require dereference and assignment + } + TT i, j; + }; + + template + struct InputIteratorConcept + { + void constraints() { + function_requires< TrivialIteratorConcept >(); + // require iterator_traits typedef's +#ifndef BOOST_NO_STD_ITERATOR_TRAITS + typedef typename std::iterator_traits::difference_type D; + 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< + typename std::iterator_traits::iterator_category, + std::input_iterator_tag> >(); +#endif + ++i; // require preincrement operator + i++; // require postincrement operator + } + TT i; + }; + + template + struct OutputIteratorConcept + { + void constraints() { + function_requires< AssignableConcept >(); + ++i; // require preincrement operator + i++; // require postincrement operator + *i++ = t; // require postincrement and assignment + } + TT i, j; + ValueT t; + }; + + template + struct ForwardIteratorConcept + { + void constraints() { + function_requires< InputIteratorConcept >(); +#ifndef BOOST_NO_STD_ITERATOR_TRAITS + function_requires< ConvertibleConcept< + typename std::iterator_traits::iterator_category, + std::forward_iterator_tag> >(); + typedef typename std::iterator_traits::reference reference; + reference r = *i; + ignore_unused_variable_warning(r); +#endif + } + TT i; + }; + + template + struct Mutable_ForwardIteratorConcept + { + void constraints() { + function_requires< ForwardIteratorConcept >(); + *i++ = *i; // require postincrement and assignment + } + TT i; + }; + + template + struct BidirectionalIteratorConcept + { + void constraints() { + function_requires< ForwardIteratorConcept >(); +#ifndef BOOST_NO_STD_ITERATOR_TRAITS + function_requires< ConvertibleConcept< + typename std::iterator_traits::iterator_category, + std::bidirectional_iterator_tag> >(); +#endif + --i; // require predecrement operator + i--; // require postdecrement operator + } + TT i; + }; + + template + struct Mutable_BidirectionalIteratorConcept + { + void constraints() { + function_requires< BidirectionalIteratorConcept >(); + function_requires< Mutable_ForwardIteratorConcept >(); + *i-- = *i; // require postdecrement and assignment + } + TT i; + }; + + + template + struct RandomAccessIteratorConcept + { + void constraints() { + function_requires< BidirectionalIteratorConcept >(); + function_requires< ComparableConcept >(); +#ifndef BOOST_NO_STD_ITERATOR_TRAITS + function_requires< ConvertibleConcept< + typename std::iterator_traits::iterator_category, + std::random_access_iterator_tag> >(); + typedef typename std::iterator_traits::reference R; +#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 + } + 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 + }; + + template + struct Mutable_RandomAccessIteratorConcept + { + void constraints() { + function_requires< RandomAccessIteratorConcept >(); + function_requires< Mutable_BidirectionalIteratorConcept >(); + 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 + }; + + //=========================================================================== + // Container Concepts + + template + struct ContainerConcept + { + 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; + + void constraints() { + function_requires< InputIteratorConcept >(); + function_requires< AssignableConcept >(); + const Container c; + i = c.begin(); + i = c.end(); + n = c.size(); + n = c.max_size(); + b = c.empty(); + } + bool b; + const_iterator i; + size_type n; + }; + + template + struct Mutable_ContainerConcept + { + typedef typename Container::value_type value_type; + 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; + }; + + template + struct ForwardContainerConcept + { + void constraints() { + function_requires< ContainerConcept >(); + typedef typename ForwardContainer::const_iterator const_iterator; + function_requires< ForwardIteratorConcept >(); + } + }; + + template + struct Mutable_ForwardContainerConcept + { + void constraints() { + function_requires< ForwardContainerConcept >(); + function_requires< Mutable_ContainerConcept >(); + typedef typename ForwardContainer::iterator iterator; + function_requires< Mutable_ForwardIteratorConcept >(); + } + }; + + template + struct ReversibleContainerConcept + { + typedef typename ReversibleContainer::const_iterator const_iterator; + typedef typename ReversibleContainer::const_reverse_iterator + const_reverse_iterator; + + void constraints() { + function_requires< ForwardContainerConcept >(); + function_requires< BidirectionalIteratorConcept >(); + function_requires< BidirectionalIteratorConcept >(); + + const ReversibleContainer c; + const_reverse_iterator i = c.rbegin(); + i = c.rend(); + } + }; + + template + struct Mutable_ReversibleContainerConcept + { + 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; + }; + + template + struct RandomAccessContainerConcept + { + 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; + + void constraints() { + function_requires< ReversibleContainerConcept >(); + function_requires< RandomAccessIteratorConcept >(); + function_requires< RandomAccessIteratorConcept >(); + + const RandomAccessContainer c; + const_reference r = c[n]; + ignore_unused_variable_warning(r); + } + size_type n; + }; + + template + struct Mutable_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; + }; + + // A Sequence is inherently mutable + template + struct SequenceConcept + { + + typedef typename Sequence::reference reference; + typedef typename Sequence::const_reference const_reference; + + void constraints() { + // Matt Austern's book puts DefaultConstructible here, the C++ + // standard places it in Container + // function_requires< DefaultConstructible >(); + function_requires< Mutable_ForwardContainerConcept >(); + function_requires< DefaultConstructibleConcept >(); + + Sequence + c(n), + c2(n, t), + c3(first, last); + + c.insert(p, t); + c.insert(p, n, t); + c.insert(p, first, last); + + c.erase(p); + c.erase(p, q); + + 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; + }; + + template + struct FrontInsertionSequenceConcept + { + void constraints() { + function_requires< SequenceConcept >(); + + c.push_front(t); + c.pop_front(); + } + FrontInsertionSequence c; + typename FrontInsertionSequence::value_type t; + }; + + template + struct BackInsertionSequenceConcept + { + 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& c) { + const_reference r = c.back(); + ignore_unused_variable_warning(r); + }; + BackInsertionSequence c; + typename BackInsertionSequence::value_type t; + }; + + template + struct AssociativeContainerConcept + { + 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& c) { + ci = c.find(k); + n = c.count(k); + cr = c.equal_range(k); + } + typedef typename AssociativeContainer::iterator iterator; + typedef typename AssociativeContainer::const_iterator const_iterator; + + 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 + { + void constraints() { + function_requires< AssociativeContainerConcept >(); + + UniqueAssociativeContainer c(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; + }; + + template + struct MultipleAssociativeContainerConcept + { + void constraints() { + function_requires< AssociativeContainerConcept >(); + + MultipleAssociativeContainer c(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; + }; + + template + struct SimpleAssociativeContainerConcept + { + 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; + } + }; + + template + struct PairAssociativeContainerConcept + { + 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; + } + }; + + template + struct SortedAssociativeContainerConcept + { + void constraints() { + function_requires< AssociativeContainerConcept >(); + function_requires< ReversibleContainerConcept >(); + + 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); + + 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(); + + 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; + }; + + // HashedAssociativeContainer + +} // namespace boost + +#endif // BOOST_CONCEPT_CHECKS_HPP +