diff --git a/include/boost/pending/concept_archetypes.hpp b/include/boost/pending/concept_archetypes.hpp index d859291..3d1d063 100644 --- a/include/boost/pending/concept_archetypes.hpp +++ b/include/boost/pending/concept_archetypes.hpp @@ -57,49 +57,6 @@ namespace boost { } }; - template - class left_equality_comparable_archetype : public Base { - public: - left_equality_comparable_archetype(detail::dummy_constructor x) - : Base(x) { } - }; - template - bool operator==(const Left&, const left_equality_comparable_archetype&) - { return true; } - template - bool operator!=(const Left&, const left_equality_comparable_archetype&) - { return true; } - - template - class equality_comparable_archetype : public Base { - public: - equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { } - }; - template - bool operator==(const equality_comparable_archetype&, - const equality_comparable_archetype&) { return true; } - template - bool operator!=(const equality_comparable_archetype&, - const equality_comparable_archetype&) { return true; } - - template - class less_than_comparable_archetype : public Base { - public: - less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { } - }; - template - bool operator<(const less_than_comparable_archetype&, - const less_than_comparable_archetype&) { return true; } - template - bool operator<=(const less_than_comparable_archetype&, - const less_than_comparable_archetype&) { return true; } - template - bool operator>(const less_than_comparable_archetype&, - const less_than_comparable_archetype&) { return true; } - template - bool operator>=(const less_than_comparable_archetype&, - const less_than_comparable_archetype&) { return true; } - template class convertible_to_archetype : public Base { public: @@ -107,6 +64,73 @@ namespace boost { operator const T&() const { return static_object::get(); } }; + 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 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 + 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 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 + boolean_archetype + operator<=(const less_than_comparable_archetype&, + const less_than_comparable_archetype&) + { return boolean_archetype(dummy_cons);; } + template + boolean_archetype + operator>(const less_than_comparable_archetype&, + const less_than_comparable_archetype&) + { return boolean_archetype(dummy_cons);; } + template + boolean_archetype + operator>=(const less_than_comparable_archetype&, + const less_than_comparable_archetype&) + { return boolean_archetype(dummy_cons);; } + template class default_constructible_archetype : public Base { public: @@ -139,7 +163,7 @@ namespace boost { template class unary_function_archetype { public: - const Return& operator()(const Arg&) { + const Return& operator()(const Arg&) { return static_object::get(); } }; @@ -147,25 +171,34 @@ namespace boost { template class binary_function_archetype { public: - const Return& operator()(const Arg1&, const Arg2&) { + const Return& operator()(const Arg1&, const Arg2&) { return static_object::get(); } }; template class unary_predicate_archetype { - typedef convertible_to_archetype Return; + typedef boolean_archetype Return; public: - const Return& operator()(const Arg&) { + const Return& operator()(const Arg&) { return static_object::get(); } }; template class binary_predicate_archetype { - typedef convertible_to_archetype Return; + typedef boolean_archetype Return; public: - const Return& operator()(const Arg1&, const Arg2&) { + const Return& operator()(const Arg1&, const Arg2&) { + return static_object::get(); + } + }; + + template + class const_binary_predicate_archetype { + typedef boolean_archetype Return; + public: + const Return& operator()(const Arg1&, const Arg2&) const { return static_object::get(); } }; diff --git a/include/boost/pending/concept_checks.hpp b/include/boost/pending/concept_checks.hpp index 35d8a8e..97ef173 100644 --- a/include/boost/pending/concept_checks.hpp +++ b/include/boost/pending/concept_checks.hpp @@ -186,27 +186,29 @@ template void ignore_unused_variable_warning(const T&) { } T b; }; - template - struct Boolean_concept { - void constraints() { - b = x; - b = x || x; - b = x && x; - } - TT x; - bool b; - }; + // 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 T& t) { + bool x = t; + ignore_unused_variable_warning(x); + } template struct EqualityComparable_concept { void constraints() { - require_boolean_return(a == b); - require_boolean_return(a != b); + require_boolean_expr(a == b); + require_boolean_expr(a != b); } - // Can't move the following outside, because it changes when - // the error message appears. - template void require_boolean_return(B) { REQUIRE(B, Boolean); } + bool boolean; TT a, b; }; @@ -214,10 +216,9 @@ template void ignore_unused_variable_warning(const T&) { } struct LeftEqualityComparable_concept { void constraints() { - require_boolean_return(b == a); - require_boolean_return(b != a); + require_boolean_expr(b == a); + require_boolean_expr(b != a); } - template void require_boolean_return(B) { REQUIRE(B, Boolean); } XX a; YY b; }; @@ -226,14 +227,12 @@ template void ignore_unused_variable_warning(const T&) { } struct LessThanComparable_concept { void constraints() { - require_boolean_return(a < b); - require_boolean_return(a > b); - require_boolean_return(a <= b); - require_boolean_return(a >= b); + require_boolean_expr(a < b); + require_boolean_expr(a > b); + require_boolean_expr(a <= b); + require_boolean_expr(a >= b); } - // Can't move the following outside, because it changes when - // the error message appears. - template void require_boolean_return(B) { REQUIRE(B, Boolean); } + bool boolean; TT a, b; }; @@ -467,39 +466,37 @@ template void ignore_unused_variable_warning(const T&) { } }; #endif - template + template struct UnaryPredicate_concept { void constraints() { - __r = __f(__arg); // require operator() returning bool + require_boolean_expr(f(arg)); // require operator() returning bool } - _Func __f; - _Arg __arg; - bool __r; + Func f; + Arg arg; }; - template + template struct BinaryPredicate_concept { void constraints() { - __r = __f(__a, __b); // require operator() returning bool + require_boolean_expr(f(a, b)); // require operator() returning bool } - _Func __f; - _First __a; - _Second __b; - bool __r; + Func f; + First a; + Second b; }; // use this when functor is used inside a container class like std::set - template + template struct Const_BinaryPredicate_concept { void constraints() { - REQUIRE3(_Func,_First,_Second, BinaryPredicate); - bool __r = __f(__a,__b); // operator() must be a const member function + REQUIRE3(Func, First, Second, BinaryPredicate); + require_boolean_expr(f(a, b)); // operator() must be a const member function } - _Func __f; - _First __a; - _Second __b; + const Func f; + First a; + Second b; }; #define __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ @@ -828,7 +825,7 @@ template void ignore_unused_variable_warning(const T&) { } REQUIRE(SimpleAssociativeContainer, AssociativeContainer); typedef typename SimpleAssociativeContainer::key_type key_type; typedef typename SimpleAssociativeContainer::value_type value_type; - CLASS_REQUIRES_SAME_TYPE(key_type, value_type); + REQUIRE_SAME_TYPE(key_type, value_type); } }; @@ -841,7 +838,7 @@ template void ignore_unused_variable_warning(const T&) { } typedef typename SimpleAssociativeContainer::value_type value_type; typedef typename SimpleAssociativeContainer::mapped_type mapped_type; typedef std::pair required_value_type; - CLASS_REQUIRES_SAME_TYPE(value_type, required_value_type); + REQUIRE_SAME_TYPE(value_type, required_value_type); } }; diff --git a/stl_concept_covering.cpp b/stl_concept_covering.cpp index b9b8fbd..63fd7d0 100644 --- a/stl_concept_covering.cpp +++ b/stl_concept_covering.cpp @@ -24,7 +24,9 @@ main() //=========================================================================== // First verify that the archetype classes model the concepts they // are suppose to. - + { + REQUIRE2(boolean_archetype, bool, Convertible); + } { typedef unary_function_archetype F; REQUIRE3(F, int, int, UnaryFunction); @@ -40,6 +42,8 @@ main() { typedef binary_predicate_archetype F; REQUIRE3(F, int, int, BinaryPredicate); + typedef const_binary_predicate_archetype const_F; + REQUIRE3(const_F, int, int, Const_BinaryPredicate); } { typedef input_iterator_archetype Iter;