forked from boostorg/concept_check
changes to the handling of bool return types
[SVN r8092]
This commit is contained in:
@@ -57,49 +57,6 @@ namespace boost {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Left, class Base = null_archetype>
|
|
||||||
class left_equality_comparable_archetype : public Base {
|
|
||||||
public:
|
|
||||||
left_equality_comparable_archetype(detail::dummy_constructor x)
|
|
||||||
: Base(x) { }
|
|
||||||
};
|
|
||||||
template <class Left>
|
|
||||||
bool operator==(const Left&, const left_equality_comparable_archetype<Left>&)
|
|
||||||
{ return true; }
|
|
||||||
template <class Left>
|
|
||||||
bool operator!=(const Left&, const left_equality_comparable_archetype<Left>&)
|
|
||||||
{ return true; }
|
|
||||||
|
|
||||||
template <class Base = null_archetype>
|
|
||||||
class equality_comparable_archetype : public Base {
|
|
||||||
public:
|
|
||||||
equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { }
|
|
||||||
};
|
|
||||||
template <class Base>
|
|
||||||
bool operator==(const equality_comparable_archetype<Base>&,
|
|
||||||
const equality_comparable_archetype<Base>&) { return true; }
|
|
||||||
template <class Base>
|
|
||||||
bool operator!=(const equality_comparable_archetype<Base>&,
|
|
||||||
const equality_comparable_archetype<Base>&) { return true; }
|
|
||||||
|
|
||||||
template <class Base = null_archetype>
|
|
||||||
class less_than_comparable_archetype : public Base {
|
|
||||||
public:
|
|
||||||
less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { }
|
|
||||||
};
|
|
||||||
template <class Base>
|
|
||||||
bool operator<(const less_than_comparable_archetype<Base>&,
|
|
||||||
const less_than_comparable_archetype<Base>&) { return true; }
|
|
||||||
template <class Base>
|
|
||||||
bool operator<=(const less_than_comparable_archetype<Base>&,
|
|
||||||
const less_than_comparable_archetype<Base>&) { return true; }
|
|
||||||
template <class Base>
|
|
||||||
bool operator>(const less_than_comparable_archetype<Base>&,
|
|
||||||
const less_than_comparable_archetype<Base>&) { return true; }
|
|
||||||
template <class Base>
|
|
||||||
bool operator>=(const less_than_comparable_archetype<Base>&,
|
|
||||||
const less_than_comparable_archetype<Base>&) { return true; }
|
|
||||||
|
|
||||||
template <class T, class Base = null_archetype>
|
template <class T, class Base = null_archetype>
|
||||||
class convertible_to_archetype : public Base {
|
class convertible_to_archetype : public Base {
|
||||||
public:
|
public:
|
||||||
@@ -107,6 +64,73 @@ namespace boost {
|
|||||||
operator const T&() const { return static_object<T>::get(); }
|
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>
|
||||||
|
class left_equality_comparable_archetype : public Base {
|
||||||
|
public:
|
||||||
|
left_equality_comparable_archetype(detail::dummy_constructor x)
|
||||||
|
: Base(x) { }
|
||||||
|
};
|
||||||
|
template <class Left>
|
||||||
|
boolean_archetype
|
||||||
|
operator==(const Left&, const left_equality_comparable_archetype<Left>&)
|
||||||
|
{ return boolean_archetype(dummy_cons); }
|
||||||
|
template <class Left>
|
||||||
|
boolean_archetype
|
||||||
|
operator!=(const Left&, const left_equality_comparable_archetype<Left>&)
|
||||||
|
{ return boolean_archetype(dummy_cons); }
|
||||||
|
|
||||||
|
template <class Base = null_archetype>
|
||||||
|
class equality_comparable_archetype : public Base {
|
||||||
|
public:
|
||||||
|
equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { }
|
||||||
|
};
|
||||||
|
template <class Base>
|
||||||
|
boolean_archetype
|
||||||
|
operator==(const equality_comparable_archetype<Base>&,
|
||||||
|
const equality_comparable_archetype<Base>&)
|
||||||
|
{ return boolean_archetype(dummy_cons);; }
|
||||||
|
template <class Base>
|
||||||
|
boolean_archetype
|
||||||
|
operator!=(const equality_comparable_archetype<Base>&,
|
||||||
|
const equality_comparable_archetype<Base>&)
|
||||||
|
{ return boolean_archetype(dummy_cons);; }
|
||||||
|
|
||||||
|
template <class Base = null_archetype>
|
||||||
|
class less_than_comparable_archetype : public Base {
|
||||||
|
public:
|
||||||
|
less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { }
|
||||||
|
};
|
||||||
|
template <class Base>
|
||||||
|
boolean_archetype
|
||||||
|
operator<(const less_than_comparable_archetype<Base>&,
|
||||||
|
const less_than_comparable_archetype<Base>&)
|
||||||
|
{ return boolean_archetype(dummy_cons);; }
|
||||||
|
template <class Base>
|
||||||
|
boolean_archetype
|
||||||
|
operator<=(const less_than_comparable_archetype<Base>&,
|
||||||
|
const less_than_comparable_archetype<Base>&)
|
||||||
|
{ return boolean_archetype(dummy_cons);; }
|
||||||
|
template <class Base>
|
||||||
|
boolean_archetype
|
||||||
|
operator>(const less_than_comparable_archetype<Base>&,
|
||||||
|
const less_than_comparable_archetype<Base>&)
|
||||||
|
{ return boolean_archetype(dummy_cons);; }
|
||||||
|
template <class Base>
|
||||||
|
boolean_archetype
|
||||||
|
operator>=(const less_than_comparable_archetype<Base>&,
|
||||||
|
const less_than_comparable_archetype<Base>&)
|
||||||
|
{ return boolean_archetype(dummy_cons);; }
|
||||||
|
|
||||||
template <class Base = null_archetype>
|
template <class Base = null_archetype>
|
||||||
class default_constructible_archetype : public Base {
|
class default_constructible_archetype : public Base {
|
||||||
public:
|
public:
|
||||||
@@ -139,7 +163,7 @@ namespace boost {
|
|||||||
template <class Arg, class Return>
|
template <class Arg, class Return>
|
||||||
class unary_function_archetype {
|
class unary_function_archetype {
|
||||||
public:
|
public:
|
||||||
const Return& operator()(const Arg&) {
|
const Return& operator()(const Arg&) {
|
||||||
return static_object<Return>::get();
|
return static_object<Return>::get();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -147,25 +171,34 @@ namespace boost {
|
|||||||
template <class Arg1, class Arg2, class Return>
|
template <class Arg1, class Arg2, class Return>
|
||||||
class binary_function_archetype {
|
class binary_function_archetype {
|
||||||
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 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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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();
|
return static_object<Return>::get();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -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
|
||||||
TT x;
|
// specify stuff about all the logical operators.
|
||||||
bool b;
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user