From 86b1612338e4d17983757f54254ddb42e46c2b63 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 20 Nov 2000 18:17:52 +0000 Subject: [PATCH] some concept checking changes as per review comments [SVN r8268] --- class_concept_checks_fail_expected1.cpp | 29 ++ class_concept_checks_fail_expected2.cpp | 29 ++ class_concept_checks_fail_expected3.cpp | 29 ++ class_concept_checks_fail_expected4.cpp | 27 ++ class_concept_checks_test.cpp | 36 ++ concept_checking.html | 4 +- concept_checks_fail_expected1.cpp | 24 + concept_checks_fail_expected2.cpp | 24 + concept_checks_fail_expected3.cpp | 24 + concept_checks_fail_expected4.cpp | 24 + concept_checks_test.cpp | 92 ++++ include/boost/pending/concept_archetypes.hpp | 82 +++- include/boost/pending/concept_checks.hpp | 446 +++++++++++-------- stl_concept_checks.cpp | 59 ++- stl_concept_covering.cpp | 59 +-- 15 files changed, 711 insertions(+), 277 deletions(-) create mode 100644 class_concept_checks_fail_expected1.cpp create mode 100644 class_concept_checks_fail_expected2.cpp create mode 100644 class_concept_checks_fail_expected3.cpp create mode 100644 class_concept_checks_fail_expected4.cpp create mode 100644 class_concept_checks_test.cpp create mode 100644 concept_checks_fail_expected1.cpp create mode 100644 concept_checks_fail_expected2.cpp create mode 100644 concept_checks_fail_expected3.cpp create mode 100644 concept_checks_fail_expected4.cpp create mode 100644 concept_checks_test.cpp diff --git a/class_concept_checks_fail_expected1.cpp b/class_concept_checks_fail_expected1.cpp new file mode 100644 index 0000000..f3bf60a --- /dev/null +++ b/class_concept_checks_fail_expected1.cpp @@ -0,0 +1,29 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_CLASS_REQUIRES macro + of the Boost Concept Checking Library catches errors + when it is suppose to. + +*/ + +struct foo { }; + +class class_requires_test +{ + BOOST_CLASS_REQUIRES(foo, EqualityComparableConcept); +}; + +int +main() +{ + class_requires_test x; + return 0; +} diff --git a/class_concept_checks_fail_expected2.cpp b/class_concept_checks_fail_expected2.cpp new file mode 100644 index 0000000..e63127e --- /dev/null +++ b/class_concept_checks_fail_expected2.cpp @@ -0,0 +1,29 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_CLASS_REQUIRES2 macro + of the Boost Concept Checking Library catches errors + when it is suppose to. + +*/ + +struct foo { }; + +class class_requires_test +{ + BOOST_CLASS_REQUIRES2(foo, foo, Comparable2Concept); +}; + +int +main() +{ + class_requires_test x; + return 0; +} diff --git a/class_concept_checks_fail_expected3.cpp b/class_concept_checks_fail_expected3.cpp new file mode 100644 index 0000000..6c17f31 --- /dev/null +++ b/class_concept_checks_fail_expected3.cpp @@ -0,0 +1,29 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_CLASS_REQUIRES3 macro + of the Boost Concept Checking Library catches errors + when it is suppose to. + +*/ + +struct foo { }; + +class class_requires_test +{ + BOOST_CLASS_REQUIRES3(foo, foo, foo, UnaryFunctionConcept); +}; + +int +main() +{ + class_requires_test x; + return 0; +} diff --git a/class_concept_checks_fail_expected4.cpp b/class_concept_checks_fail_expected4.cpp new file mode 100644 index 0000000..bbbf468 --- /dev/null +++ b/class_concept_checks_fail_expected4.cpp @@ -0,0 +1,27 @@ +// (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. + +#include + +/* + This file verifies that the BOOST_CLASS_REQUIRES4 macro + of the Boost Concept Checking Library catches errors + when it is suppose to. +*/ + +struct foo { }; + +class class_requires_test +{ + BOOST_CLASS_REQUIRES4(foo, foo, foo, foo, BinaryFunctionConcept); +}; + +int +main() +{ + class_requires_test x; + return 0; +} diff --git a/class_concept_checks_test.cpp b/class_concept_checks_test.cpp new file mode 100644 index 0000000..d9667c0 --- /dev/null +++ b/class_concept_checks_test.cpp @@ -0,0 +1,36 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_CLASS_REQUIRES macros of the + Boost Concept Checking Library do not cause errors when + they are not suppose to. + +*/ + +struct foo { bool operator()(int) { return true; } }; +struct bar { bool operator()(int, char) { return true; } }; + +class class_requires_test +{ + BOOST_CLASS_REQUIRES(int, EqualityComparableConcept); + typedef int* int_ptr; + typedef const int* const_int_ptr; + BOOST_CLASS_REQUIRES2(int_ptr, const_int_ptr, Comparable2Concept); + BOOST_CLASS_REQUIRES3(foo, bool, int, UnaryFunctionConcept); + BOOST_CLASS_REQUIRES4(bar, bool, int, char, BinaryFunctionConcept); +}; + +int +main() +{ + class_requires_test x; + ignore_unused_variable_warning(x); + return 0; +} diff --git a/concept_checking.html b/concept_checking.html index 10583f1..57d71a0 100644 --- a/concept_checking.html +++ b/concept_checking.html @@ -399,9 +399,9 @@ As an example of how to create a concept checking class, we look at how to create the corresponding checks for the RandomAccessIterator concept. First, as a convention we name the -concept checking class after the concept, and add the prefix +concept checking class after the concept, and add the suffix ``_concept''. Note that the REQUIRE macro expects -the prefix to be there. Next we must define a member function named +the suffix to be there. Next we must define a member function named constraints() in which we will exercise the valid expressions of the concept. The REQUIRE macro expects this function's signature to appear exactly as it is appears below: a void diff --git a/concept_checks_fail_expected1.cpp b/concept_checks_fail_expected1.cpp new file mode 100644 index 0000000..1618639 --- /dev/null +++ b/concept_checks_fail_expected1.cpp @@ -0,0 +1,24 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_FUNCTION_REQUIRES macro + of the Boost Concept Checking Library catches errors + when it is suppose to. + +*/ + +struct foo { }; + +int +main() +{ + BOOST_FUNCTION_REQUIRES(foo, EqualityComparableConcept); + return 0; +} diff --git a/concept_checks_fail_expected2.cpp b/concept_checks_fail_expected2.cpp new file mode 100644 index 0000000..c951aa3 --- /dev/null +++ b/concept_checks_fail_expected2.cpp @@ -0,0 +1,24 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_FUNCTION_REQUIRES2 macro + of the Boost Concept Checking Library catches errors + when it is suppose to. + +*/ + +struct foo { }; + +int +main() +{ + BOOST_FUNCTION_REQUIRES2(foo, foo, Comparable2Concept); + return 0; +} diff --git a/concept_checks_fail_expected3.cpp b/concept_checks_fail_expected3.cpp new file mode 100644 index 0000000..42db55a --- /dev/null +++ b/concept_checks_fail_expected3.cpp @@ -0,0 +1,24 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_FUNCTION_REQUIRES3 macro + of the Boost Concept Checking Library catches errors + when it is suppose to. + +*/ + +struct foo { }; + +int +main() +{ + BOOST_FUNCTION_REQUIRES3(foo, foo, foo, UnaryFunctionConcept); + return 0; +} diff --git a/concept_checks_fail_expected4.cpp b/concept_checks_fail_expected4.cpp new file mode 100644 index 0000000..314cdd5 --- /dev/null +++ b/concept_checks_fail_expected4.cpp @@ -0,0 +1,24 @@ +// (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. + +#include + +/* + + This file verifies that the BOOST_FUNCTION_REQUIRES4 macro + of the Boost Concept Checking Library catches errors + when it is suppose to. + +*/ + +struct foo { }; + +int +main() +{ + BOOST_FUNCTION_REQUIRES4(foo, foo, foo, foo, BinaryFunctionConcept); + return 0; +} diff --git a/concept_checks_test.cpp b/concept_checks_test.cpp new file mode 100644 index 0000000..c79b571 --- /dev/null +++ b/concept_checks_test.cpp @@ -0,0 +1,92 @@ +// (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. + +#include +#include + +/* + + This file verifies that the BOOST_FUNCTION_REQUIRES macros of the + Boost Concept Checking Library do not cause errors when they are not + suppose to and verifies that the concept archetypes meet the + requirements of their matching concepts. + +*/ + + +int +main() +{ + using namespace boost; + { + typedef default_constructible_archetype<> foo; + BOOST_FUNCTION_REQUIRES(foo, DefaultConstructibleConcept); + } + { + typedef copy_constructible_archetype<> foo; + BOOST_FUNCTION_REQUIRES(foo, CopyConstructibleConcept); + } + { + typedef assignable_archetype<> foo; + BOOST_FUNCTION_REQUIRES(foo, AssignableConcept); + } + { + typedef copy_constructible_archetype<> foo; + typedef convertible_to_archetype convertible_to_foo; + BOOST_FUNCTION_REQUIRES2(convertible_to_foo, foo, ConvertibleConcept); + } + { + BOOST_FUNCTION_REQUIRES2(boolean_archetype, bool, ConvertibleConcept); + } + { + typedef unary_function_archetype F; + BOOST_FUNCTION_REQUIRES3(F, int, int, UnaryFunctionConcept); + } + { + typedef binary_function_archetype F; + BOOST_FUNCTION_REQUIRES4(F, int, int, int, BinaryFunctionConcept); + } + { + typedef unary_predicate_archetype F; + BOOST_FUNCTION_REQUIRES2(F, int, UnaryPredicateConcept); + } + { + typedef binary_predicate_archetype F; + BOOST_FUNCTION_REQUIRES3(F, int, int, BinaryPredicateConcept); + typedef const_binary_predicate_archetype const_F; + BOOST_FUNCTION_REQUIRES3(const_F, int, int, Const_BinaryPredicateConcept); + } + { + typedef trivial_iterator_archetype Iter; + BOOST_FUNCTION_REQUIRES(Iter, TrivialIteratorConcept); + } + { + typedef mutable_trivial_iterator_archetype Iter; + BOOST_FUNCTION_REQUIRES(Iter, Mutable_TrivialIteratorConcept); + } + { + typedef input_iterator_archetype Iter; + BOOST_FUNCTION_REQUIRES(Iter, InputIteratorConcept); + } + { + typedef output_iterator_archetype Iter; + BOOST_FUNCTION_REQUIRES2(Iter, int, OutputIteratorConcept); + } + { + typedef forward_iterator_archetype Iter; + BOOST_FUNCTION_REQUIRES(Iter, ForwardIteratorConcept); + } + { + typedef bidirectional_iterator_archetype Iter; + BOOST_FUNCTION_REQUIRES(Iter, BidirectionalIteratorConcept); + } + { + typedef random_access_iterator_archetype Iter; + BOOST_FUNCTION_REQUIRES(Iter, RandomAccessIteratorConcept); + } + + return 0; +} diff --git a/include/boost/pending/concept_archetypes.hpp b/include/boost/pending/concept_archetypes.hpp index 3d1d063..19b2ef8 100644 --- a/include/boost/pending/concept_archetypes.hpp +++ b/include/boost/pending/concept_archetypes.hpp @@ -89,6 +89,7 @@ namespace boost { operator!=(const Left&, const left_equality_comparable_archetype&) { return boolean_archetype(dummy_cons); } + template class equality_comparable_archetype : public Base { public: @@ -105,6 +106,25 @@ namespace boost { const equality_comparable_archetype&) { return boolean_archetype(dummy_cons);; } + + template + class equality_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 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); + } + }; + + template class less_than_comparable_archetype : public Base { public: @@ -115,22 +135,65 @@ namespace boost { 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 less_than_comparable_archetype&, - const less_than_comparable_archetype&) + operator<(const comparable_archetype&, + const comparable_archetype&) { return boolean_archetype(dummy_cons);; } template boolean_archetype - operator>(const less_than_comparable_archetype&, - const less_than_comparable_archetype&) + operator<=(const comparable_archetype&, + const comparable_archetype&) { return boolean_archetype(dummy_cons);; } template boolean_archetype - operator>=(const less_than_comparable_archetype&, - const less_than_comparable_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 + 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); + } + }; + + template class default_constructible_archetype : public Base { public: @@ -138,6 +201,7 @@ namespace boost { default_constructible_archetype(detail::dummy_constructor x) : Base(x) { } }; + template class copy_constructible_archetype : public Base { public: @@ -155,7 +219,7 @@ namespace boost { } assignable_archetype(detail::dummy_constructor x) : Base(x) { } }; - + //=========================================================================== // Function Object Archetype Classes @@ -245,8 +309,7 @@ namespace boost { template struct input_output_proxy { input_output_proxy& operator=(const T&) { return *this; } - operator T() { return t; } - T t; + operator const T&() { return static_object::get(); } }; template class mutable_trivial_iterator_archetype @@ -265,7 +328,6 @@ namespace boost { bool operator==(const self&) const { return true; } bool operator!=(const self&) const { return true; } input_output_proxy operator*() { return input_output_proxy(); } - T x; }; } // namespace boost diff --git a/include/boost/pending/concept_checks.hpp b/include/boost/pending/concept_checks.hpp index 7b6a921..0f40fe8 100644 --- a/include/boost/pending/concept_checks.hpp +++ b/include/boost/pending/concept_checks.hpp @@ -5,76 +5,75 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. // -#ifndef BOOST_GRAPH_DETAIL_CONCEPT_CHECKS_HPP -#define BOOST_GRAPH_DETAIL_CONCEPT_CHECKS_HPP +#ifndef BOOST_CONCEPT_CHECKS_HPP +#define BOOST_CONCEPT_CHECKS_HPP #include #include #include #include -#if defined(__GNUC__) || defined(__KCC) || defined(__ghs) || defined(__MWERKS__) +#if (__GNUC__) || defined(__KCC) || defined(__ghs) || defined(__MWERKS__) #define BOOST_FPTR & #else #define BOOST_FPTR #endif -#define REQUIRE(__type_var, __concept) \ +#define BOOST_FUNCTION_REQUIRES(type_var, concept) \ do { \ - void (__concept##_concept <__type_var>::*__x)() = \ - BOOST_FPTR __concept##_concept <__type_var>::constraints; \ - __x = __x; } while (0) + void (concept::*x)() = BOOST_FPTR concept::constraints; \ + x = x; } while (0) -#define REQUIRE2(__type_var1, __type_var2, __concept) \ +#define BOOST_FUNCTION_REQUIRES2(type_var1, type_var2, concept) \ do { \ - void (__concept##_concept <__type_var1, __type_var2>::*__x)() = \ - BOOST_FPTR __concept##_concept <__type_var1, __type_var2>::constraints; \ - __x = __x; } while (0) + void (concept::*x)() = \ + BOOST_FPTR concept::constraints; \ + x = x; } while (0) -#define REQUIRE3(__type_var1, __type_var2, __type_var3,__concept) \ +#define BOOST_FUNCTION_REQUIRES3(type_var1, type_var2, type_var3,concept) \ do { \ - void (__concept##_concept <__type_var1, __type_var2, __type_var3>::*__x)() = \ - BOOST_FPTR __concept##_concept <__type_var1, __type_var2, __type_var3>::constraints; \ - __x = __x; } while (0) + void (concept ::*x)() = \ + BOOST_FPTR concept ::constraints; \ + x = x; } while (0) -#define REQUIRE4(__type_var1, __type_var2, __type_var3,__type_var4,__concept) \ +#define BOOST_FUNCTION_REQUIRES4(type_var1, type_var2, type_var3,type_var4,concept) \ do { \ - void (__concept##_concept <__type_var1,__type_var2,__type_var3,__type_var4>::*__x)() = \ - BOOST_FPTR __concept##_concept <__type_var1, __type_var2, __type_var3, __type_var4>::constraints;\ - __x = __x; } while (0) + void (concept ::*x)() = \ + BOOST_FPTR concept ::constraints;\ + x = x; } while (0) -#define CLASS_REQUIRES(__tv, __concept) \ - typedef void (__concept##_concept <__tv>::* __func##__tv##__concept)(); \ - template <__func##__tv##__concept _Tp1> \ - struct __dummy_struct_##__tv##__concept { }; \ - typedef __dummy_struct_##__tv##__concept< \ - BOOST_FPTR __concept##_concept <__tv>::constraints> \ - __dummy_typedef_##__tv##__concept +#define BOOST_CLASS_REQUIRES(type_var, concept) \ + typedef void (concept ::* __func##type_var##concept)(); \ + template <__func##type_var##concept _Tp1> \ + struct __dummy_struct_##type_var##concept { }; \ + typedef __dummy_struct_##type_var##concept< \ + BOOST_FPTR concept ::constraints> \ + __dummy_typedef_##type_var##concept -#define CLASS_REQUIRES2(__tv1, __tv2, __concept) \ - typedef void (__concept##_concept <__tv1,__tv2>::* __func##__tv1##__tv2##__concept)(); \ - template <__func##__tv1##__tv2##__concept _Tp1> \ - struct __dummy_struct_##__tv1##__tv2##__concept { }; \ - typedef __dummy_struct_##__tv1##__tv2##__concept< \ - BOOST_FPTR __concept##_concept <__tv1,__tv2>::constraints> \ - __dummy_typedef_##__tv1##__tv2##__concept +#define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept) \ + typedef void (concept ::* __func##type_var1##type_var2##concept)(); \ + template <__func##type_var1##type_var2##concept _Tp1> \ + struct __dummy_struct_##type_var1##type_var2##concept { }; \ + typedef __dummy_struct_##type_var1##type_var2##concept< \ + BOOST_FPTR concept ::constraints> \ + __dummy_typedef_##type_var1##type_var2##concept -#define CLASS_REQUIRES3(__tv1, __tv2, __tv3, __concept) \ - typedef void (__concept##_concept <__tv1,__tv2,__tv3>::* __func##__tv1##__tv2##__tv3##__concept)(); \ - template <__func##__tv1##__tv2##__tv3##__concept _Tp1> \ - struct __dummy_struct_##__tv1##__tv2##__tv3##__concept { }; \ - typedef __dummy_struct_##__tv1##__tv2##__tv3##__concept< \ - BOOST_FPTR __concept##_concept <__tv1,__tv2,__tv3>::constraints> \ - __dummy_typedef_##__tv1##__tv2##__tv3##__concept +#define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept) \ + typedef void (concept ::* __func##type_var1##type_var2##type_var3##concept)(); \ + template <__func##type_var1##type_var2##type_var3##concept _Tp1> \ + struct __dummy_struct_##type_var1##type_var2##type_var3##concept { }; \ + typedef __dummy_struct_##type_var1##type_var2##type_var3##concept< \ + BOOST_FPTR concept ::constraints> \ + __dummy_typedef_##type_var1##type_var2##type_var3##concept -#define CLASS_REQUIRES4(__tv1, __tv2, __tv3, __tv4, __concept) \ - typedef void (__concept##_concept <__tv1,__tv2,__tv3,__tv4>::* __func##__tv1##__tv2##__tv3##__tv4##__concept)(); \ - template <__func##__tv1##__tv2##__tv3##__tv4##__concept _Tp1> \ - struct __dummy_struct_##__tv1##__tv2##__tv3##__tv4##__concept { }; \ - typedef __dummy_struct_##__tv1##__tv2##__tv3##__tv4##__concept< \ - BOOST_FPTR __concept##_concept <__tv1,__tv2,__tv3,__tv4>::constraints> \ - __dummy_typedef_##__tv1##__tv2##__tv3##__tv4##__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 <__func##type_var1##type_var2##type_var3##type_var4##concept _Tp1> \ + struct __dummy_struct_##type_var1##type_var2##type_var3##type_var4##concept { }; \ + typedef __dummy_struct_##type_var1##type_var2##type_var3##type_var4##concept< \ + BOOST_FPTR concept ::constraints> \ + __dummy_typedef_##type_var1##type_var2##type_var3##type_var4##concept #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -88,16 +87,16 @@ template struct require_same_type { typedef T type; }; #endif -#define REQUIRE_SAME_TYPE(X,Y) \ +#define BOOST_FUNCTION_REQUIRES_SAME_TYPE(X,Y) \ typedef typename require_same_type::type X##_same_##Y -#define CLASS_REQUIRES_SAME_TYPE(X,Y) \ +#define BOOST_CLASS_REQUIRES_SAME_TYPE(X,Y) \ typedef typename require_same_type::type X##_same_##Y template void ignore_unused_variable_warning(const T&) { } template - struct Integer_concept { + struct IntegerConcept { void constraints() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION error__type_must_be_an_integer_type(); @@ -105,17 +104,17 @@ template void ignore_unused_variable_warning(const T&) { } } }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template <> struct Integer_concept { void constraints() {} }; - template <> struct Integer_concept { void constraints() {} }; - template <> struct Integer_concept { void constraints() {} }; - template <> struct Integer_concept { void constraints() {} }; - template <> struct Integer_concept { void constraints() {} }; - template <> struct Integer_concept { 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() {} }; + template <> struct IntegerConcept { void constraints() {} }; // etc. #endif template - struct SignedInteger_concept { + struct SignedIntegerConcept { void constraints() { #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION error__type_must_be_a_signed_integer_type(); @@ -123,9 +122,9 @@ template void ignore_unused_variable_warning(const T&) { } } }; #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - template <> struct SignedInteger_concept { void constraints() {} }; - template <> struct SignedInteger_concept { void constraints() {} }; - template <> struct SignedInteger_concept { void constraints() {} }; + template <> struct SignedIntegerConcept { void constraints() {} }; + template <> struct SignedIntegerConcept { void constraints() {} }; + template <> struct SignedIntegerConcept { void constraints() {} }; // etc. #endif @@ -133,7 +132,7 @@ template void ignore_unused_variable_warning(const T&) { } // Basic Concepts template - struct Convertible_concept + struct ConvertibleConcept { void constraints() { Y y = x; @@ -142,11 +141,8 @@ template void ignore_unused_variable_warning(const T&) { } X x; }; - // Issue, the SGI STL version of Assignable is - // different from the C++ standard definition of Assignable. - // This follows the C++ standard version. template - struct Assignable_concept + struct AssignableConcept { void constraints() { #if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL @@ -163,7 +159,24 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct DefaultConstructible_concept + 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 @@ -172,16 +185,19 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct CopyConstructible_concept + struct CopyConstructibleConcept { void constraints() { T a(b); // require copy constructor T* ptr = &a; // require address of operator const_constraints(a); + ignore_unused_variable_warning(ptr); } void const_constraints(const T& a) { T c(a); // require const copy constructor const T* ptr = &a; // require const address of operator + ignore_unused_variable_warning(c); + ignore_unused_variable_warning(ptr); } T b; }; @@ -202,7 +218,7 @@ template void ignore_unused_variable_warning(const T&) { } } template - struct EqualityComparable_concept + struct EqualityComparableConcept { void constraints() { require_boolean_expr(a == b); @@ -213,18 +229,34 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct LeftEqualityComparable_concept + struct EqualityComparable2Concept { void constraints() { + require_boolean_expr(a == b); require_boolean_expr(b == a); + require_boolean_expr(a != b); require_boolean_expr(b != a); } XX a; YY b; }; + // Use LessThanOpConcept (see below) instead of + // LessThanComparableConcept when you want to express comparison + // between two different types. template - struct LessThanComparable_concept + struct LessThanComparableConcept + { + void constraints() { + require_boolean_expr(a < b); + } + bool boolean; + TT a, b; + }; + + // This is equivalent to SGI STL's LessThanComparable. + template + struct ComparableConcept { void constraints() { require_boolean_expr(a < b); @@ -236,16 +268,34 @@ template void ignore_unused_variable_warning(const T&) { } TT a, b; }; + template + struct Comparable2Concept + { + void constraints() { + 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); + } + bool boolean; + XX a; + YY b; + }; + //=========================================================================== // Iterator Concepts template - struct TrivialIterator_concept + struct TrivialIteratorConcept { void constraints() { - REQUIRE(TT, Assignable); - REQUIRE(TT, DefaultConstructible); - REQUIRE(TT, EqualityComparable); + BOOST_FUNCTION_REQUIRES(TT, AssignableConcept); + BOOST_FUNCTION_REQUIRES(TT, DefaultConstructibleConcept); + BOOST_FUNCTION_REQUIRES(TT, EqualityComparableConcept); #ifndef BOOST_NO_STD_ITERATOR_TRAITS typedef typename std::iterator_traits::value_type V; #endif @@ -255,29 +305,29 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct Mutable_TrivialIterator_concept + struct Mutable_TrivialIteratorConcept { void constraints() { - REQUIRE(TT, TrivialIterator); + BOOST_FUNCTION_REQUIRES(TT, TrivialIteratorConcept); *i = *j; // require dereference and assignment } TT i, j; }; template - struct InputIterator_concept + struct InputIteratorConcept { void constraints() { - REQUIRE(TT, TrivialIterator); + BOOST_FUNCTION_REQUIRES(TT, TrivialIteratorConcept); // require iterator_traits typedef's #ifndef BOOST_NO_STD_ITERATOR_TRAITS typedef typename std::iterator_traits::difference_type D; - REQUIRE(D, SignedInteger); + BOOST_FUNCTION_REQUIRES(D, SignedIntegerConcept); typedef typename std::iterator_traits::reference R; typedef typename std::iterator_traits::pointer P; typedef typename std::iterator_traits::iterator_category C; - REQUIRE2(typename std::iterator_traits::iterator_category, - std::input_iterator_tag, Convertible); + BOOST_FUNCTION_REQUIRES2(typename std::iterator_traits::iterator_category, + std::input_iterator_tag, ConvertibleConcept); #endif ++i; // require preincrement operator i++; // require postincrement operator @@ -286,10 +336,10 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct OutputIterator_concept + struct OutputIteratorConcept { void constraints() { - REQUIRE(TT, Assignable); + BOOST_FUNCTION_REQUIRES(TT, AssignableConcept); ++i; // require preincrement operator i++; // require postincrement operator *i++ = t; // require postincrement and assignment @@ -299,13 +349,13 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct ForwardIterator_concept + struct ForwardIteratorConcept { void constraints() { - REQUIRE(TT, InputIterator); + BOOST_FUNCTION_REQUIRES(TT, InputIteratorConcept); #ifndef BOOST_NO_STD_ITERATOR_TRAITS - REQUIRE2(typename std::iterator_traits::iterator_category, - std::forward_iterator_tag, Convertible); + BOOST_FUNCTION_REQUIRES2(typename std::iterator_traits::iterator_category, + std::forward_iterator_tag, ConvertibleConcept); typedef typename std::iterator_traits::reference reference; reference r = *i; ignore_unused_variable_warning(r); @@ -315,23 +365,23 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct Mutable_ForwardIterator_concept + struct Mutable_ForwardIteratorConcept { void constraints() { - REQUIRE(TT, ForwardIterator); + BOOST_FUNCTION_REQUIRES(TT, ForwardIteratorConcept); *i++ = *i; // require postincrement and assignment } TT i; }; template - struct BidirectionalIterator_concept + struct BidirectionalIteratorConcept { void constraints() { - REQUIRE(TT, ForwardIterator); + BOOST_FUNCTION_REQUIRES(TT, ForwardIteratorConcept); #ifndef BOOST_NO_STD_ITERATOR_TRAITS - REQUIRE2(typename std::iterator_traits::iterator_category, - std::bidirectional_iterator_tag, Convertible); + BOOST_FUNCTION_REQUIRES2(typename std::iterator_traits::iterator_category, + std::bidirectional_iterator_tag, ConvertibleConcept); #endif --i; // require predecrement operator i--; // require postdecrement operator @@ -340,11 +390,11 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct Mutable_BidirectionalIterator_concept + struct Mutable_BidirectionalIteratorConcept { void constraints() { - REQUIRE(TT, BidirectionalIterator); - REQUIRE(TT, Mutable_ForwardIterator); + BOOST_FUNCTION_REQUIRES(TT, BidirectionalIteratorConcept); + BOOST_FUNCTION_REQUIRES(TT, Mutable_ForwardIteratorConcept); *i-- = *i; // require postdecrement and assignment } TT i; @@ -352,14 +402,14 @@ template void ignore_unused_variable_warning(const T&) { } template - struct RandomAccessIterator_concept + struct RandomAccessIteratorConcept { void constraints() { - REQUIRE(TT, BidirectionalIterator); - REQUIRE(TT, LessThanComparable); + BOOST_FUNCTION_REQUIRES(TT, BidirectionalIteratorConcept); + BOOST_FUNCTION_REQUIRES(TT, ComparableConcept); #ifndef BOOST_NO_STD_ITERATOR_TRAITS - REQUIRE2(typename std::iterator_traits::iterator_category, - std::random_access_iterator_tag, Convertible); + BOOST_FUNCTION_REQUIRES2(typename std::iterator_traits::iterator_category, + std::random_access_iterator_tag, ConvertibleConcept); typedef typename std::iterator_traits::reference R; #endif @@ -380,11 +430,11 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct Mutable_RandomAccessIterator_concept + struct Mutable_RandomAccessIteratorConcept { void constraints() { - REQUIRE(TT, RandomAccessIterator); - REQUIRE(TT, Mutable_BidirectionalIterator); + BOOST_FUNCTION_REQUIRES(TT, RandomAccessIteratorConcept); + BOOST_FUNCTION_REQUIRES(TT, Mutable_BidirectionalIteratorConcept); i[n] = *i; // require element access and assignment } TT i; @@ -399,7 +449,7 @@ template void ignore_unused_variable_warning(const T&) { } // Function Object Concepts template - struct Generator_concept + struct GeneratorConcept { void constraints() { __r = __f(); // require operator() member function @@ -411,7 +461,7 @@ template void ignore_unused_variable_warning(const T&) { } #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - struct Generator_concept<_Func,void> + struct GeneratorConcept<_Func,void> { void constraints() { __f(); // require operator() member function @@ -421,7 +471,7 @@ template void ignore_unused_variable_warning(const T&) { } #endif template - struct UnaryFunction_concept + struct UnaryFunctionConcept { void constraints() { __r = __f(__arg); // require operator() @@ -433,7 +483,7 @@ template void ignore_unused_variable_warning(const T&) { } #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - struct UnaryFunction_concept<_Func,void,_Arg> { + struct UnaryFunctionConcept<_Func,void,_Arg> { void constraints() { __f(__arg); // require operator() } @@ -442,7 +492,7 @@ template void ignore_unused_variable_warning(const T&) { } #endif template - struct BinaryFunction_concept + struct BinaryFunctionConcept { void constraints() { __r = __f(__first, __second); // require operator() @@ -455,7 +505,7 @@ template void ignore_unused_variable_warning(const T&) { } #if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - struct BinaryFunction_concept<_Func,void,_First,_Second> + struct BinaryFunctionConcept<_Func,void,_First,_Second> { void constraints() { __f(__first, __second); // require operator() @@ -467,7 +517,7 @@ template void ignore_unused_variable_warning(const T&) { } #endif template - struct UnaryPredicate_concept + struct UnaryPredicateConcept { void constraints() { require_boolean_expr(f(arg)); // require operator() returning bool @@ -477,7 +527,7 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct BinaryPredicate_concept + struct BinaryPredicateConcept { void constraints() { require_boolean_expr(f(a, b)); // require operator() returning bool @@ -489,12 +539,12 @@ template void ignore_unused_variable_warning(const T&) { } // use this when functor is used inside a container class like std::set template - struct Const_BinaryPredicate_concept { + struct Const_BinaryPredicateConcept { void constraints() { const_constraints(f); } void const_constraints(const Func& fun) { - REQUIRE3(Func, First, Second, BinaryPredicate); + BOOST_FUNCTION_REQUIRES3(Func, First, Second, BinaryPredicateConcept); // operator() must be a const member function require_boolean_expr(fun(a, b)); } @@ -503,34 +553,46 @@ template void ignore_unused_variable_warning(const T&) { } Second b; }; -#define __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ - template \ - struct _NAME##_concept { \ - void constraints() { (void)_constraints(); } \ - _Ret _constraints() { \ - return __a _OP __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; \ + First a; \ + Second b; \ } - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(==, _OP_EQUAL); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(!=, _OP_NOT_EQUAL); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(<, _OP_LESS_THAN); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(<=, _OP_LESS_EQUAL); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(>, _OP_GREATER_THAN); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(>=, _OP_GREATER_EQUAL); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _OP_PLUS); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _OP_TIMES); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _OP_DIVIDE); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _OP_SUBTRACT); - __STL_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _OP_MOD); +#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ + template \ + struct NAME { \ + void constraints() { (void)constraints_(); } \ + Ret constraints_() { \ + Ret x = 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 template - struct Container_concept + struct ContainerConcept { typedef typename Container::value_type value_type; typedef typename Container::difference_type difference_type; @@ -540,8 +602,8 @@ template void ignore_unused_variable_warning(const T&) { } typedef typename Container::const_iterator const_iterator; void constraints() { - REQUIRE(const_iterator, InputIterator); - REQUIRE(Container, Assignable); + BOOST_FUNCTION_REQUIRES(const_iterator, InputIteratorConcept); + BOOST_FUNCTION_REQUIRES(Container, AssignableConcept); const Container c; i = c.begin(); i = c.end(); @@ -555,7 +617,7 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct Mutable_Container_concept + struct Mutable_ContainerConcept { typedef typename Container::value_type value_type; typedef typename Container::reference reference; @@ -563,9 +625,9 @@ template void ignore_unused_variable_warning(const T&) { } typedef typename Container::pointer pointer; void constraints() { - REQUIRE(Container, Container); - REQUIRE(value_type, Assignable); - REQUIRE(iterator, InputIterator); + BOOST_FUNCTION_REQUIRES(Container, ContainerConcept); + BOOST_FUNCTION_REQUIRES(value_type, AssignableConcept); + BOOST_FUNCTION_REQUIRES(iterator, InputIteratorConcept); i = c.begin(); i = c.end(); @@ -576,37 +638,37 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct ForwardContainer_concept + struct ForwardContainerConcept { void constraints() { - REQUIRE(ForwardContainer, Container); + BOOST_FUNCTION_REQUIRES(ForwardContainer, ContainerConcept); typedef typename ForwardContainer::const_iterator const_iterator; - REQUIRE(const_iterator, ForwardIterator); + BOOST_FUNCTION_REQUIRES(const_iterator, ForwardIteratorConcept); } }; template - struct Mutable_ForwardContainer_concept + struct Mutable_ForwardContainerConcept { void constraints() { - REQUIRE(ForwardContainer, ForwardContainer); - REQUIRE(ForwardContainer, Mutable_Container); + BOOST_FUNCTION_REQUIRES(ForwardContainer, ForwardContainerConcept); + BOOST_FUNCTION_REQUIRES(ForwardContainer, Mutable_ContainerConcept); typedef typename ForwardContainer::iterator iterator; - REQUIRE(iterator, Mutable_ForwardIterator); + BOOST_FUNCTION_REQUIRES(iterator, Mutable_ForwardIteratorConcept); } }; template - struct ReversibleContainer_concept + struct ReversibleContainerConcept { typedef typename ReversibleContainer::const_iterator const_iterator; typedef typename ReversibleContainer::const_reverse_iterator const_reverse_iterator; void constraints() { - REQUIRE(ReversibleContainer, ForwardContainer); - REQUIRE(const_iterator, BidirectionalIterator); - REQUIRE(const_reverse_iterator, BidirectionalIterator); + BOOST_FUNCTION_REQUIRES(ReversibleContainer, ForwardContainerConcept); + BOOST_FUNCTION_REQUIRES(const_iterator, BidirectionalIteratorConcept); + BOOST_FUNCTION_REQUIRES(const_reverse_iterator, BidirectionalIteratorConcept); const ReversibleContainer c; const_reverse_iterator i = c.rbegin(); @@ -615,16 +677,16 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct Mutable_ReversibleContainer_concept + struct Mutable_ReversibleContainerConcept { typedef typename ReversibleContainer::iterator iterator; typedef typename ReversibleContainer::reverse_iterator reverse_iterator; void constraints() { - REQUIRE(ReversibleContainer, ReversibleContainer); - REQUIRE(ReversibleContainer, Mutable_ForwardContainer); - REQUIRE(iterator, Mutable_BidirectionalIterator); - REQUIRE(reverse_iterator, Mutable_BidirectionalIterator); + BOOST_FUNCTION_REQUIRES(ReversibleContainer, ReversibleContainerConcept); + BOOST_FUNCTION_REQUIRES(ReversibleContainer, Mutable_ForwardContainerConcept); + BOOST_FUNCTION_REQUIRES(iterator, Mutable_BidirectionalIteratorConcept); + BOOST_FUNCTION_REQUIRES(reverse_iterator, Mutable_BidirectionalIteratorConcept); reverse_iterator i = c.rbegin(); i = c.rend(); @@ -633,7 +695,7 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct RandomAccessContainer_concept + struct RandomAccessContainerConcept { typedef typename RandomAccessContainer::size_type size_type; typedef typename RandomAccessContainer::const_reference const_reference; @@ -642,9 +704,9 @@ template void ignore_unused_variable_warning(const T&) { } const_reverse_iterator; void constraints() { - REQUIRE(RandomAccessContainer, ReversibleContainer); - REQUIRE(const_iterator, RandomAccessIterator); - REQUIRE(const_reverse_iterator, RandomAccessIterator); + BOOST_FUNCTION_REQUIRES(RandomAccessContainer, ReversibleContainerConcept); + BOOST_FUNCTION_REQUIRES(const_iterator, RandomAccessIteratorConcept); + BOOST_FUNCTION_REQUIRES(const_reverse_iterator, RandomAccessIteratorConcept); const RandomAccessContainer c; const_reference r = c[n]; @@ -654,7 +716,7 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct Mutable_RandomAccessContainer_concept + struct Mutable_RandomAccessContainerConcept { typedef typename RandomAccessContainer::size_type size_type; typedef typename RandomAccessContainer::reference reference; @@ -662,10 +724,10 @@ template void ignore_unused_variable_warning(const T&) { } typedef typename RandomAccessContainer::reverse_iterator reverse_iterator; void constraints() { - REQUIRE(RandomAccessContainer, RandomAccessContainer); - REQUIRE(RandomAccessContainer, Mutable_ReversibleContainer); - REQUIRE(iterator, Mutable_RandomAccessIterator); - REQUIRE(reverse_iterator, Mutable_RandomAccessIterator); + BOOST_FUNCTION_REQUIRES(RandomAccessContainer, RandomAccessContainerConcept); + BOOST_FUNCTION_REQUIRES(RandomAccessContainer, Mutable_ReversibleContainerConcept); + BOOST_FUNCTION_REQUIRES(iterator, Mutable_RandomAccessIteratorConcept); + BOOST_FUNCTION_REQUIRES(reverse_iterator, Mutable_RandomAccessIteratorConcept); reference r = c[i]; ignore_unused_variable_warning(r); @@ -676,18 +738,18 @@ template void ignore_unused_variable_warning(const T&) { } // A Sequence is inherently mutable template - struct Sequence_concept + struct SequenceConcept { - // Matt put's DefaultConstructible here, the C++ standard - // places it in Container - // CLASS_REQUIRES(Sequence, DefaultConstructible); + // Matt Austern's book puts DefaultConstructible here, the C++ + // standard places it in Container + // BOOST_CLASS_REQUIRES(Sequence, DefaultConstructible); typedef typename Sequence::reference reference; typedef typename Sequence::const_reference const_reference; void constraints() { - REQUIRE(Sequence, Mutable_ForwardContainer); - REQUIRE(Sequence, DefaultConstructible); + BOOST_FUNCTION_REQUIRES(Sequence, Mutable_ForwardContainerConcept); + BOOST_FUNCTION_REQUIRES(Sequence, DefaultConstructibleConcept); Sequence c(n), @@ -720,10 +782,10 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct FrontInsertionSequence_concept + struct FrontInsertionSequenceConcept { void constraints() { - REQUIRE(FrontInsertionSequence, Sequence); + BOOST_FUNCTION_REQUIRES(FrontInsertionSequence, SequenceConcept); c.push_front(t); c.pop_front(); @@ -733,13 +795,13 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct BackInsertionSequence_concept + struct BackInsertionSequenceConcept { typedef typename BackInsertionSequence::reference reference; typedef typename BackInsertionSequence::const_reference const_reference; void constraints() { - REQUIRE(BackInsertionSequence, Sequence); + BOOST_FUNCTION_REQUIRES(BackInsertionSequence, SequenceConcept); c.push_back(t); c.pop_back(); @@ -755,11 +817,11 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct AssociativeContainer_concept + struct AssociativeContainerConcept { void constraints() { - REQUIRE(AssociativeContainer, ForwardContainer); - REQUIRE(AssociativeContainer, DefaultConstructible); + BOOST_FUNCTION_REQUIRES(AssociativeContainer, ForwardContainerConcept); + BOOST_FUNCTION_REQUIRES(AssociativeContainer, DefaultConstructibleConcept); i = c.find(k); r = c.equal_range(k); @@ -786,10 +848,10 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct UniqueAssociativeContainer_concept + struct UniqueAssociativeContainerConcept { void constraints() { - REQUIRE(UniqueAssociativeContainer, AssociativeContainer); + BOOST_FUNCTION_REQUIRES(UniqueAssociativeContainer, AssociativeContainerConcept); UniqueAssociativeContainer c(first, last); @@ -804,10 +866,10 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct MultipleAssociativeContainer_concept + struct MultipleAssociativeContainerConcept { void constraints() { - REQUIRE(MultipleAssociativeContainer, AssociativeContainer); + BOOST_FUNCTION_REQUIRES(MultipleAssociativeContainer, AssociativeContainerConcept); MultipleAssociativeContainer c(first, last); @@ -823,35 +885,35 @@ template void ignore_unused_variable_warning(const T&) { } }; template - struct SimpleAssociativeContainer_concept + struct SimpleAssociativeContainerConcept { void constraints() { - REQUIRE(SimpleAssociativeContainer, AssociativeContainer); + BOOST_FUNCTION_REQUIRES(SimpleAssociativeContainer, AssociativeContainerConcept); typedef typename SimpleAssociativeContainer::key_type key_type; typedef typename SimpleAssociativeContainer::value_type value_type; - REQUIRE_SAME_TYPE(key_type, value_type); + BOOST_FUNCTION_REQUIRES_SAME_TYPE(key_type, value_type); } }; template - struct PairAssociativeContainer_concept + struct PairAssociativeContainerConcept { void constraints() { - REQUIRE(SimpleAssociativeContainer, AssociativeContainer); + BOOST_FUNCTION_REQUIRES(SimpleAssociativeContainer, 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; - REQUIRE_SAME_TYPE(value_type, required_value_type); + BOOST_FUNCTION_REQUIRES_SAME_TYPE(value_type, required_value_type); } }; template - struct SortedAssociativeContainer_concept + struct SortedAssociativeContainerConcept { void constraints() { - REQUIRE(SortedAssociativeContainer, AssociativeContainer); - REQUIRE(SortedAssociativeContainer, ReversibleContainer); + BOOST_FUNCTION_REQUIRES(SortedAssociativeContainer, AssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(SortedAssociativeContainer, ReversibleContainerConcept); SortedAssociativeContainer c(kc), @@ -891,5 +953,5 @@ template void ignore_unused_variable_warning(const T&) { } // HashedAssociativeContainer -#endif /* BOOST_GRAPH_DETAIL_CONCEPT_CHECKS_H */ +#endif // BOOST_CONCEPT_CHECKS_HPP diff --git a/stl_concept_checks.cpp b/stl_concept_checks.cpp index f0f0648..f8a64ee 100644 --- a/stl_concept_checks.cpp +++ b/stl_concept_checks.cpp @@ -4,6 +4,15 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. +// +// This file checks to see if various standard container +// implementations live up to requirements specified in the C++ +// standard. As many implementations do not live to the requirements, +// it is not uncommon for this file to fail to compile. The +// BOOST_HIDE_EXPECTED_ERRORS macro is provided here if you want to +// see as much of this file compile as possible. +// + #include #include @@ -16,10 +25,12 @@ #include #endif +//#define BOOST_HIDE_EXPECTED_ERRORS + int main() { -#if defined(_ITERATOR_) +#if defined(_ITERATOR_) && defined(BOOST_HIDE_EXPECTED_ERRORS) // VC++ STL implementation is not standard conformant and // fails to pass these concept checks #else @@ -28,27 +39,27 @@ main() typedef std::list List; // VC++ missing pointer and const_pointer typedefs - REQUIRE(Vector, Mutable_RandomAccessContainer); - REQUIRE(Vector, BackInsertionSequence); + BOOST_FUNCTION_REQUIRES(Vector, Mutable_RandomAccessContainerConcept); + BOOST_FUNCTION_REQUIRES(Vector, BackInsertionSequenceConcept); -#if !defined(__GNUC__) -#if !defined __sgi +#if !(defined(__GNUC__) && defined(BOOST_HIDE_EXPECTED_ERRORS)) +#if !(defined(__sgi) && defined(BOOST_HIDE_EXPECTED_ERRORS)) // old deque iterator missing n + iter operation - REQUIRE(Deque, Mutable_RandomAccessContainer); + BOOST_FUNCTION_REQUIRES(Deque, Mutable_RandomAccessContainerConcept); #endif // warnings about signed and unsigned in old deque version - REQUIRE(Deque, FrontInsertionSequence); - REQUIRE(Deque, BackInsertionSequence); + BOOST_FUNCTION_REQUIRES(Deque, FrontInsertionSequenceConcept); + BOOST_FUNCTION_REQUIRES(Deque, BackInsertionSequenceConcept); #endif // VC++ missing pointer and const_pointer typedefs - REQUIRE(List, Mutable_ReversibleContainer); - REQUIRE(List, FrontInsertionSequence); - REQUIRE(List, BackInsertionSequence); + BOOST_FUNCTION_REQUIRES(List, Mutable_ReversibleContainerConcept); + BOOST_FUNCTION_REQUIRES(List, FrontInsertionSequenceConcept); + BOOST_FUNCTION_REQUIRES(List, BackInsertionSequenceConcept); #ifndef BOOST_NO_SLIST typedef std::slist SList; - REQUIRE(SList, FrontInsertionSequence); + BOOST_FUNCTION_REQUIRES(SList, FrontInsertionSequenceConcept); #endif typedef std::set Set; @@ -56,21 +67,21 @@ main() typedef std::map Map; typedef std::multimap MultiMap; - REQUIRE(Set, SortedAssociativeContainer); - REQUIRE(Set, SimpleAssociativeContainer); - REQUIRE(Set, UniqueAssociativeContainer); + BOOST_FUNCTION_REQUIRES(Set, SortedAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(Set, SimpleAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(Set, UniqueAssociativeContainerConcept); - REQUIRE(MultiSet, SortedAssociativeContainer); - REQUIRE(MultiSet, SimpleAssociativeContainer); - REQUIRE(MultiSet, MultipleAssociativeContainer); + BOOST_FUNCTION_REQUIRES(MultiSet, SortedAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(MultiSet, SimpleAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(MultiSet, MultipleAssociativeContainerConcept); - REQUIRE(Map, SortedAssociativeContainer); - REQUIRE(Map, UniqueAssociativeContainer); - REQUIRE(Map, PairAssociativeContainer); + BOOST_FUNCTION_REQUIRES(Map, SortedAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(Map, UniqueAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(Map, PairAssociativeContainerConcept); - REQUIRE(MultiMap, SortedAssociativeContainer); - REQUIRE(MultiMap, MultipleAssociativeContainer); - REQUIRE(MultiMap, PairAssociativeContainer); + BOOST_FUNCTION_REQUIRES(MultiMap, SortedAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(MultiMap, MultipleAssociativeContainerConcept); + BOOST_FUNCTION_REQUIRES(MultiMap, PairAssociativeContainerConcept); #endif return 0; diff --git a/stl_concept_covering.cpp b/stl_concept_covering.cpp index 63fd7d0..88cd1dd 100644 --- a/stl_concept_covering.cpp +++ b/stl_concept_covering.cpp @@ -21,51 +21,6 @@ main() { using namespace boost; - //=========================================================================== - // 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); - } - { - typedef binary_function_archetype F; - REQUIRE4(F, int, int, int, BinaryFunction); - } - { - typedef unary_predicate_archetype F; - REQUIRE2(F, int, UnaryPredicate); - } - { - 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; - REQUIRE(Iter, InputIterator); - } - { - typedef output_iterator_archetype Iter; - REQUIRE2(Iter, int, OutputIterator); - } - { - typedef forward_iterator_archetype Iter; - REQUIRE(Iter, ForwardIterator); - } - { - typedef bidirectional_iterator_archetype Iter; - REQUIRE(Iter, BidirectionalIterator); - } - { - typedef random_access_iterator_archetype Iter; - REQUIRE(Iter, RandomAccessIterator); - } - //=========================================================================== // Non-mutating Algorithms { @@ -75,17 +30,17 @@ main() } { /* - SGI STL Docs and the C++ standard (25.1.2) requirements for + SGI STL Docs and the C++ standard (25.1.2) BOOST_FUNCTION_REQUIRESments for std::for_each() are broken. They should be specified as follows: template InputIterator find(InputIterator first, InputIterator last, const LeftEqualityComparable& value) { - REQUIRE(InputIterator, InputIterator); + BOOST_FUNCTION_REQUIRES(InputIterator, InputIterator); typedef typename std::iterator_traits::value_type value_type; - REQUIRE(LeftEqualityComparable, value_type, LeftEqualityComparable); + BOOST_FUNCTION_REQUIRES(LeftEqualityComparable, value_type, LeftEqualityComparable); ... } */ @@ -119,10 +74,11 @@ main() { typedef input_iterator_archetype InIter; InIter in; - REQUIRE(InIter, InputIterator); + BOOST_FUNCTION_REQUIRES(InIter, InputIteratorConcept); left_equality_comparable_archetype value(dummy_cons); std::iterator_traits::difference_type n = std::count(in, in, value); + ignore_unused_variable_warning(n); } { typedef input_iterator_archetype InIter; @@ -137,6 +93,7 @@ main() unary_predicate_archetype pred; std::iterator_traits::difference_type n = std::count_if(in, in, pred); + ignore_unused_variable_warning(n); } { input_iterator_archetype< convertible_to_archetype > in; @@ -154,12 +111,14 @@ main() typedef input_iterator_archetype InIter2; InIter2 in2; std::pair p = std::mismatch(in1, in1, in2); + ignore_unused_variable_warning(p); } { typedef input_iterator_archetype< convertible_to_archetype > InIter; InIter in1, in2; binary_predicate_archetype pred; std::pair p = std::mismatch(in1, in1, in2, pred); + ignore_unused_variable_warning(p); } { // SGI STL docs: EqualityComparable not needed @@ -167,11 +126,13 @@ main() typedef left_equality_comparable_archetype Right; input_iterator_archetype in2; bool b = std::equal(in1, in1, in2); + ignore_unused_variable_warning(b); } { input_iterator_archetype< convertible_to_archetype > in1, in2; binary_predicate_archetype pred; bool b = std::equal(in1, in1, in2, pred); + ignore_unused_variable_warning(b); } { // SGI STL docs: EqualityComparable not needed