changes to the handling of bool return types

[SVN r8092]
This commit is contained in:
Jeremy Siek
2000-11-01 02:43:41 +00:00
parent 0fb40bbafa
commit 7b40323fef
3 changed files with 128 additions and 94 deletions

View File

@@ -57,6 +57,23 @@ namespace boost {
} }
}; };
template <class T, class Base = null_archetype>
class convertible_to_archetype : public Base {
public:
convertible_to_archetype(detail::dummy_constructor x) : Base(x) { }
operator const T&() const { return static_object<T>::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, class Base = null_archetype> template <class Left, class Base = null_archetype>
class left_equality_comparable_archetype : public Base { class left_equality_comparable_archetype : public Base {
public: public:
@@ -64,11 +81,13 @@ namespace boost {
: Base(x) { } : Base(x) { }
}; };
template <class Left> template <class Left>
bool operator==(const Left&, const left_equality_comparable_archetype<Left>&) boolean_archetype
{ return true; } operator==(const Left&, const left_equality_comparable_archetype<Left>&)
{ return boolean_archetype(dummy_cons); }
template <class Left> template <class Left>
bool operator!=(const Left&, const left_equality_comparable_archetype<Left>&) boolean_archetype
{ return true; } operator!=(const Left&, const left_equality_comparable_archetype<Left>&)
{ return boolean_archetype(dummy_cons); }
template <class Base = null_archetype> template <class Base = null_archetype>
class equality_comparable_archetype : public Base { class equality_comparable_archetype : public Base {
@@ -76,11 +95,15 @@ namespace boost {
equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { } equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { }
}; };
template <class Base> template <class Base>
bool operator==(const equality_comparable_archetype<Base>&, boolean_archetype
const equality_comparable_archetype<Base>&) { return true; } operator==(const equality_comparable_archetype<Base>&,
const equality_comparable_archetype<Base>&)
{ return boolean_archetype(dummy_cons);; }
template <class Base> template <class Base>
bool operator!=(const equality_comparable_archetype<Base>&, boolean_archetype
const equality_comparable_archetype<Base>&) { return true; } operator!=(const equality_comparable_archetype<Base>&,
const equality_comparable_archetype<Base>&)
{ return boolean_archetype(dummy_cons);; }
template <class Base = null_archetype> template <class Base = null_archetype>
class less_than_comparable_archetype : public Base { class less_than_comparable_archetype : public Base {
@@ -88,24 +111,25 @@ namespace boost {
less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { } less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { }
}; };
template <class Base> template <class Base>
bool operator<(const less_than_comparable_archetype<Base>&, boolean_archetype
const less_than_comparable_archetype<Base>&) { return true; } operator<(const less_than_comparable_archetype<Base>&,
const less_than_comparable_archetype<Base>&)
{ return boolean_archetype(dummy_cons);; }
template <class Base> template <class Base>
bool operator<=(const less_than_comparable_archetype<Base>&, boolean_archetype
const less_than_comparable_archetype<Base>&) { return true; } operator<=(const less_than_comparable_archetype<Base>&,
const less_than_comparable_archetype<Base>&)
{ return boolean_archetype(dummy_cons);; }
template <class Base> template <class Base>
bool operator>(const less_than_comparable_archetype<Base>&, boolean_archetype
const less_than_comparable_archetype<Base>&) { return true; } operator>(const less_than_comparable_archetype<Base>&,
const less_than_comparable_archetype<Base>&)
{ return boolean_archetype(dummy_cons);; }
template <class Base> template <class Base>
bool operator>=(const less_than_comparable_archetype<Base>&, boolean_archetype
const less_than_comparable_archetype<Base>&) { return true; } operator>=(const less_than_comparable_archetype<Base>&,
const less_than_comparable_archetype<Base>&)
template <class T, class Base = null_archetype> { return boolean_archetype(dummy_cons);; }
class convertible_to_archetype : public Base {
public:
convertible_to_archetype(detail::dummy_constructor x) : Base(x) { }
operator const T&() const { return static_object<T>::get(); }
};
template <class Base = null_archetype> template <class Base = null_archetype>
class default_constructible_archetype : public Base { class default_constructible_archetype : public Base {
@@ -154,7 +178,7 @@ namespace boost {
template <class Arg> template <class Arg>
class unary_predicate_archetype { class unary_predicate_archetype {
typedef convertible_to_archetype<bool> Return; typedef boolean_archetype Return;
public: public:
const Return& operator()(const Arg&) { const Return& operator()(const Arg&) {
return static_object<Return>::get(); return static_object<Return>::get();
@@ -163,13 +187,22 @@ namespace boost {
template <class Arg1, class Arg2> template <class Arg1, class Arg2>
class binary_predicate_archetype { class binary_predicate_archetype {
typedef convertible_to_archetype<bool> Return; typedef boolean_archetype Return;
public: public:
const Return& operator()(const Arg1&, const Arg2&) { const Return& operator()(const Arg1&, const Arg2&) {
return static_object<Return>::get(); return static_object<Return>::get();
} }
}; };
template <class Arg1, class Arg2>
class const_binary_predicate_archetype {
typedef boolean_archetype Return;
public:
const Return& operator()(const Arg1&, const Arg2&) const {
return static_object<Return>::get();
}
};
//=========================================================================== //===========================================================================
// Iterator Archetype Classes // Iterator Archetype Classes

View File

@@ -186,27 +186,29 @@ template <class T> void ignore_unused_variable_warning(const T&) { }
T b; T b;
}; };
template <class TT> // The C++ standard requirements for many concepts talk about return
struct Boolean_concept { // types that must be "convertible to bool". The problem with this
void constraints() { // requirement is that it leaves the door open for evil proxies that
b = x; // define things like operator|| with strange return types. Two
b = x || x; // possible solutions are:
b = x && x; // 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 <class T>
void require_boolean_expr(const T& t) {
bool x = t;
ignore_unused_variable_warning(x);
} }
TT x;
bool b;
};
template <class TT> template <class TT>
struct EqualityComparable_concept struct EqualityComparable_concept
{ {
void constraints() { void constraints() {
require_boolean_return(a == b); require_boolean_expr(a == b);
require_boolean_return(a != b); require_boolean_expr(a != b);
} }
// Can't move the following outside, because it changes when bool boolean;
// the error message appears.
template <class B> void require_boolean_return(B) { REQUIRE(B, Boolean); }
TT a, b; TT a, b;
}; };
@@ -214,10 +216,9 @@ template <class T> void ignore_unused_variable_warning(const T&) { }
struct LeftEqualityComparable_concept struct LeftEqualityComparable_concept
{ {
void constraints() { void constraints() {
require_boolean_return(b == a); require_boolean_expr(b == a);
require_boolean_return(b != a); require_boolean_expr(b != a);
} }
template <class B> void require_boolean_return(B) { REQUIRE(B, Boolean); }
XX a; XX a;
YY b; YY b;
}; };
@@ -226,14 +227,12 @@ template <class T> void ignore_unused_variable_warning(const T&) { }
struct LessThanComparable_concept struct LessThanComparable_concept
{ {
void constraints() { void constraints() {
require_boolean_return(a < b); require_boolean_expr(a < b);
require_boolean_return(a > b); require_boolean_expr(a > b);
require_boolean_return(a <= b); require_boolean_expr(a <= b);
require_boolean_return(a >= b); require_boolean_expr(a >= b);
} }
// Can't move the following outside, because it changes when bool boolean;
// the error message appears.
template <class B> void require_boolean_return(B) { REQUIRE(B, Boolean); }
TT a, b; TT a, b;
}; };
@@ -467,39 +466,37 @@ template <class T> void ignore_unused_variable_warning(const T&) { }
}; };
#endif #endif
template <class _Func, class _Arg> template <class Func, class Arg>
struct UnaryPredicate_concept struct UnaryPredicate_concept
{ {
void constraints() { void constraints() {
__r = __f(__arg); // require operator() returning bool require_boolean_expr(f(arg)); // require operator() returning bool
} }
_Func __f; Func f;
_Arg __arg; Arg arg;
bool __r;
}; };
template <class _Func, class _First, class _Second> template <class Func, class First, class Second>
struct BinaryPredicate_concept struct BinaryPredicate_concept
{ {
void constraints() { void constraints() {
__r = __f(__a, __b); // require operator() returning bool require_boolean_expr(f(a, b)); // require operator() returning bool
} }
_Func __f; Func f;
_First __a; First a;
_Second __b; Second b;
bool __r;
}; };
// use this when functor is used inside a container class like std::set // use this when functor is used inside a container class like std::set
template <class _Func, class _First, class _Second> template <class Func, class First, class Second>
struct Const_BinaryPredicate_concept { struct Const_BinaryPredicate_concept {
void constraints() { void constraints() {
REQUIRE3(_Func,_First,_Second, BinaryPredicate); REQUIRE3(Func, First, Second, BinaryPredicate);
bool __r = __f(__a,__b); // operator() must be a const member function require_boolean_expr(f(a, b)); // operator() must be a const member function
} }
_Func __f; const Func f;
_First __a; First a;
_Second __b; Second b;
}; };
#define __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ #define __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \
@@ -828,7 +825,7 @@ template <class T> void ignore_unused_variable_warning(const T&) { }
REQUIRE(SimpleAssociativeContainer, AssociativeContainer); REQUIRE(SimpleAssociativeContainer, AssociativeContainer);
typedef typename SimpleAssociativeContainer::key_type key_type; typedef typename SimpleAssociativeContainer::key_type key_type;
typedef typename SimpleAssociativeContainer::value_type value_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 <class T> void ignore_unused_variable_warning(const T&) { }
typedef typename SimpleAssociativeContainer::value_type value_type; typedef typename SimpleAssociativeContainer::value_type value_type;
typedef typename SimpleAssociativeContainer::mapped_type mapped_type; typedef typename SimpleAssociativeContainer::mapped_type mapped_type;
typedef std::pair<const key_type, mapped_type> required_value_type; typedef std::pair<const key_type, mapped_type> required_value_type;
CLASS_REQUIRES_SAME_TYPE(value_type, required_value_type); REQUIRE_SAME_TYPE(value_type, required_value_type);
} }
}; };

View File

@@ -24,7 +24,9 @@ main()
//=========================================================================== //===========================================================================
// First verify that the archetype classes model the concepts they // First verify that the archetype classes model the concepts they
// are suppose to. // are suppose to.
{
REQUIRE2(boolean_archetype, bool, Convertible);
}
{ {
typedef unary_function_archetype<int, int> F; typedef unary_function_archetype<int, int> F;
REQUIRE3(F, int, int, UnaryFunction); REQUIRE3(F, int, int, UnaryFunction);
@@ -40,6 +42,8 @@ main()
{ {
typedef binary_predicate_archetype<int, int> F; typedef binary_predicate_archetype<int, int> F;
REQUIRE3(F, int, int, BinaryPredicate); REQUIRE3(F, int, int, BinaryPredicate);
typedef const_binary_predicate_archetype<int, int> const_F;
REQUIRE3(const_F, int, int, Const_BinaryPredicate);
} }
{ {
typedef input_iterator_archetype<null_archetype> Iter; typedef input_iterator_archetype<null_archetype> Iter;