diff --git a/include/boost/pending/concept_archetypes.hpp b/include/boost/pending/concept_archetypes.hpp index ccb8eba..44419d9 100644 --- a/include/boost/pending/concept_archetypes.hpp +++ b/include/boost/pending/concept_archetypes.hpp @@ -20,7 +20,10 @@ namespace boost { } static detail::dummy_constructor dummy_cons; - // A type that models no concept. + // 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() { } @@ -28,6 +31,7 @@ namespace boost { null_archetype& operator=(const null_archetype&) { return *this; } public: null_archetype(detail::dummy_constructor) { } + template friend void dummy_friend(); // just to avoid warnings }; @@ -57,12 +61,71 @@ namespace boost { } }; - template + 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) { } + }; + +#if 0 + // Careful, don't use same type for T and Base. That + // results in the conversion operator being invalid. + template > class convertible_to_archetype : public Base { public: convertible_to_archetype(detail::dummy_constructor x) : Base(x) { } operator const T&() const { return static_object::get(); } }; +#else + + struct default_archetype_base { + default_archetype_base(detail::dummy_constructor x) { } + }; + + 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(); } + }; +#endif class boolean_archetype { public: @@ -74,23 +137,7 @@ namespace boost { boolean_archetype& operator=(const boolean_archetype&) { return *this; } }; - template - class left_equality_comparable_archetype : public Base { - public: - left_equality_comparable_archetype(detail::dummy_constructor x) - : Base(x) { } - }; - template - boolean_archetype - operator==(const Left&, const left_equality_comparable_archetype&) - { return boolean_archetype(dummy_cons); } - template - boolean_archetype - operator!=(const Left&, const left_equality_comparable_archetype&) - { return boolean_archetype(dummy_cons); } - - - template + template > class equality_comparable_archetype : public Base { public: equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { } @@ -107,25 +154,31 @@ namespace boost { { return boolean_archetype(dummy_cons);; } - template - class equality_comparable2_archetype { + template > + class equality_comparable2_first_archetype : public Base { public: - friend boolean_archetype operator==(const XX& x, const YY& y) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator!=(const XX& x, const YY& y) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator==(const YY& y, const XX& x) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator!=(const YY& y, const XX& x) { - return boolean_archetype(dummy_cons); - } + 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 + template > class less_than_comparable_archetype : public Base { public: less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { } @@ -134,10 +187,11 @@ namespace boost { boolean_archetype operator<(const less_than_comparable_archetype&, const less_than_comparable_archetype&) - { return boolean_archetype(dummy_cons);; } + { return boolean_archetype(dummy_cons); } - template + + template > class comparable_archetype : public Base { public: comparable_archetype(detail::dummy_constructor x) : Base(x) { } @@ -164,69 +218,79 @@ namespace boost { { return boolean_archetype(dummy_cons);; } - template - class comparable2_archetype { - public: - friend boolean_archetype operator<(const XX& x, const YY& y) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator<=(const XX& x, const YY& y) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator>(const XX& x, const YY& y) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator>=(const XX& x, const YY& y) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator<(const YY& y, const XX& x) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator<=(const YY& y, const XX& x) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator>(const YY& y, const XX& x) { - return boolean_archetype(dummy_cons); - } - friend boolean_archetype operator>=(const YY& y, const XX& x) { - return boolean_archetype(dummy_cons); - } - }; +#define BOOST_DEFINE_BINARY_PREDICATE_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 \ + 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) - template - class default_constructible_archetype : public Base { - public: - default_constructible_archetype() : Base(dummy_cons) { } - default_constructible_archetype(detail::dummy_constructor x) : Base(x) { } - }; +#define BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(OP, NAME) \ + template > \ + class NAME##_first_archetype : public Base { }; \ + \ + template > \ + class NAME##_second_archetype : public Base { }; \ + \ + template \ + Return \ + operator OP (const NAME##_first_archetype&, \ + const NAME##_second_archetype&) \ + { \ + return Return(dummy_cons); \ + } + // The default constructor used in Return() above is bad. - 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 assignable_archetype : public Base { - public: - assignable_archetype& operator=(const assignable_archetype&) { - return *this; - } - assignable_archetype(detail::dummy_constructor x) : Base(x) { } - }; - + 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(); } @@ -234,7 +298,10 @@ namespace boost { 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(); } @@ -243,7 +310,9 @@ namespace boost { 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(); } @@ -252,7 +321,9 @@ namespace boost { 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(); } @@ -261,7 +332,9 @@ namespace boost { 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(); } @@ -363,26 +436,27 @@ namespace boost { self operator++(int) { return *this; } }; + template struct output_proxy { - template 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 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(); } + reference operator*() const { return output_proxy(); } self& operator++() { return *this; } self operator++(int) { return *this; } }; diff --git a/include/boost/pending/concept_checks.hpp b/include/boost/pending/concept_checks.hpp index 71ac2fa..07edb53 100644 --- a/include/boost/pending/concept_checks.hpp +++ b/include/boost/pending/concept_checks.hpp @@ -35,6 +35,15 @@ void function_requires() // 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 \ @@ -68,6 +77,7 @@ void function_requires() concept_checking_typedef_##type_var1##type_var2##type_var3##type_var4##concept +#endif #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template @@ -135,14 +145,13 @@ struct require_same { typedef T type; }; //=========================================================================== // Basic Concepts - template - struct ConvertibleConcept + template + struct DefaultConstructibleConcept { void constraints() { - Y y = x; - ignore_unused_variable_warning(y); + TT a; // require default constructor + ignore_unused_variable_warning(a); } - X x; }; template @@ -162,32 +171,6 @@ struct require_same { typedef T type; }; TT a; }; - template - struct AssignableSGIConcept - { - 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 DefaultConstructibleConcept - { - void constraints() { - TT a; // require default constructor - ignore_unused_variable_warning(a); - } - }; - template struct CopyConstructibleConcept { @@ -206,6 +189,36 @@ struct require_same { typedef T type; }; 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 @@ -231,19 +244,6 @@ struct require_same { typedef T type; }; TT a, b; }; - template - struct EqualityComparable2Concept - { - void constraints() { - require_boolean_expr(a == b); - require_boolean_expr(b == a); - require_boolean_expr(a != b); - require_boolean_expr(b != a); - } - AA a; - BB b; - }; - template struct LessThanComparableConcept { @@ -253,25 +253,11 @@ struct require_same { typedef T type; }; TT a, b; }; - template - struct LessThanComparable2Concept - { - void constraints() { - function_requires< LessThanComparableConcept >(); - function_requires< LessThanComparableConcept >(); - require_boolean_expr(a < b); - require_boolean_expr(b < a); - } - AA a; - BB b; - }; - // This is equivalent to SGI STL's LessThanComparable. template struct ComparableConcept { void constraints() { - function_requires< EqualityComparableConcept >(); require_boolean_expr(a < b); require_boolean_expr(a > b); require_boolean_expr(a <= b); @@ -280,26 +266,146 @@ struct require_same { typedef T type; }; TT a, b; }; - // This is a generalization of SGI STL's LessThanComparable - // concept to 2 types. - template - struct Comparable2Concept +#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() { - function_requires< EqualityComparable2Concept >(); - function_requires< ComparableConcept >(); - function_requires< ComparableConcept >(); - require_boolean_expr(a < b); - require_boolean_expr(b < a); - require_boolean_expr(a > b); - require_boolean_expr(b > a); - require_boolean_expr(a <= b); - require_boolean_expr(b <= a); - require_boolean_expr(a >= b); - require_boolean_expr(b >= a); + const Return& r = f(); // require operator() member function } - AA a; - BB b; + 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; }; //=========================================================================== @@ -465,149 +571,6 @@ struct require_same { typedef T type; }; #endif }; - //=========================================================================== - // Function Object Concepts - - template - struct GeneratorConcept - { - void constraints() { - r = f(); // require operator() member function - } - Func f; - Return r; - }; - - -#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; - }; - -#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); - //=========================================================================== // Container Concepts