From 92306b4a19b544e6454ffbecdea4b9c3f9a7c9b2 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Thu, 30 Nov 2000 02:49:31 +0000 Subject: [PATCH] added tons of functions to stl_concept_covering.cpp [SVN r8359] --- concept_checking.html | 12 +- concept_checks_test.cpp | 109 ++++++++- stl_concept_covering.cpp | 492 ++++++++++++++++++++++++++++++++------- 3 files changed, 511 insertions(+), 102 deletions(-) diff --git a/concept_checking.html b/concept_checking.html index accd03e..d658842 100644 --- a/concept_checking.html +++ b/concept_checking.html @@ -249,9 +249,9 @@ with foo: EqualityComparableConcept<foo> and then find a way to get the compiler to compile the constraints() function without actually calling it. The Boost Concept Checking Library defines two utilities that make this easy: -function_requires() and class_requires. +function_requires() and BOOST_CLASS_REQUIRES. function_requires() function can be used in function bodies -and the class_requires class can be used inside class +and the BOOST_CLASS_REQUIRES macro can be used inside class bodies. The function_requires() function takes no arguments, but has a template parameter for the concept checking class. This means that the instantiated concept checking class must be given as an @@ -264,14 +264,12 @@ explicit template argument, as shown below. }; -The class_requires is a class template with a template -parameter for the concept checking class. Accessing the nested -check type within class_requires triggers the the -concept checking. +The BOOST_CLASS_REQUIRES macro can be used inside a class +definition to check whether some type models a concept.
   struct some_class_using_foo {
-    typedef class_requires< EqualityComparableConcept<foo> >::check req1;
+    BOOST_CLASS_REQUIRES(foo, EqualityComparableConcept);
   };
 
diff --git a/concept_checks_test.cpp b/concept_checks_test.cpp index 1123f00..b5fc58b 100644 --- a/concept_checks_test.cpp +++ b/concept_checks_test.cpp @@ -21,17 +21,24 @@ int main() { using namespace boost; + + //=========================================================================== + // Basic Concepts { typedef default_constructible_archetype<> foo; function_requires< DefaultConstructibleConcept >(); } + { + typedef assignable_archetype<> foo; + function_requires< AssignableConcept >(); + } { typedef copy_constructible_archetype<> foo; function_requires< CopyConstructibleConcept >(); } { - typedef assignable_archetype<> foo; - function_requires< AssignableConcept >(); + typedef sgi_assignable_archetype<> foo; + function_requires< SGIAssignableConcept >(); } { typedef copy_constructible_archetype<> foo; @@ -41,6 +48,66 @@ main() { function_requires< ConvertibleConcept >(); } + { + typedef equality_comparable_archetype<> foo; + function_requires< EqualityComparableConcept >(); + } + { + typedef less_than_comparable_archetype<> foo; + function_requires< LessThanComparableConcept >(); + } + { + typedef comparable_archetype<> foo; + function_requires< ComparableConcept >(); + } + { + typedef equal_op_first_archetype<> First; + typedef equal_op_second_archetype<> Second; + function_requires< EqualOpConcept >(); + } + { + typedef not_equal_op_first_archetype<> First; + typedef not_equal_op_second_archetype<> Second; + function_requires< NotEqualOpConcept >(); + } + { + typedef less_than_op_first_archetype<> First; + typedef less_than_op_second_archetype<> Second; + function_requires< LessThanOpConcept >(); + } + { + typedef less_equal_op_first_archetype<> First; + typedef less_equal_op_second_archetype<> Second; + function_requires< LessEqualOpConcept >(); + } + { + typedef greater_than_op_first_archetype<> First; + typedef greater_than_op_second_archetype<> Second; + function_requires< GreaterThanOpConcept >(); + } + { + typedef greater_equal_op_first_archetype<> First; + typedef greater_equal_op_second_archetype<> Second; + function_requires< GreaterEqualOpConcept >(); + } + + { + typedef copy_constructible_archetype<> Return; + typedef plus_op_first_archetype First; + typedef plus_op_second_archetype Second; + function_requires< PlusOpConcept >(); + } + + //=========================================================================== + // Function Object Concepts + + { + typedef generator_archetype > foo; + function_requires< GeneratorConcept > >(); + } + { + function_requires< GeneratorConcept< void_generator_archetype, void > >(); + } { typedef unary_function_archetype F; function_requires< UnaryFunctionConcept >(); @@ -59,16 +126,19 @@ main() typedef const_binary_predicate_archetype const_F; function_requires< Const_BinaryPredicateConcept >(); } + + //=========================================================================== + // Iterator Concepts { - typedef trivial_iterator_archetype Iter; + typedef trivial_iterator_archetype > Iter; function_requires< TrivialIteratorConcept >(); } { - typedef mutable_trivial_iterator_archetype Iter; + typedef mutable_trivial_iterator_archetype > Iter; function_requires< Mutable_TrivialIteratorConcept >(); } { - typedef input_iterator_archetype Iter; + typedef input_iterator_archetype > Iter; function_requires< InputIteratorConcept >(); } { @@ -76,17 +146,40 @@ main() function_requires< OutputIteratorConcept >(); } { - typedef forward_iterator_archetype Iter; + typedef forward_iterator_archetype > Iter; function_requires< ForwardIteratorConcept >(); } { - typedef bidirectional_iterator_archetype Iter; + typedef forward_iterator_archetype > Iter; + function_requires< Mutable_ForwardIteratorConcept >(); + } + { + typedef bidirectional_iterator_archetype > Iter; function_requires< BidirectionalIteratorConcept >(); } { - typedef random_access_iterator_archetype Iter; + typedef bidirectional_iterator_archetype > Iter; + function_requires< Mutable_BidirectionalIteratorConcept >(); + } + { + typedef random_access_iterator_archetype > Iter; function_requires< RandomAccessIteratorConcept >(); } + { + typedef random_access_iterator_archetype > Iter; + function_requires< Mutable_RandomAccessIteratorConcept >(); + } + + //=========================================================================== + // Container Concepts + + { + + function_requires< ContainerConcept< > >(); + } + { + + } return 0; } diff --git a/stl_concept_covering.cpp b/stl_concept_covering.cpp index 0fe838a..d3e8350 100644 --- a/stl_concept_covering.cpp +++ b/stl_concept_covering.cpp @@ -10,12 +10,40 @@ /* - This file uses the archetype classes to verify whether the concept - requirements documented for the STL algorithms actually *cover* the - algorithms true requirements. + This file uses the archetype classes to find out which concepts + actually *cover* the algorithms true requirements. The + archetypes/concepts chosen do not necessarily match the C++ standard + or the SGI STL documentation, but instead were chosen based on the + minimal concepts that current STL implementations require, which in + many cases is less stringent than the standard. It is an open issue + as to whether the C++ standard should be changed to reflect these + weaker requirements. */ +#define BOOST_HIDE_EXPECTED_ERRORS + + // This is a special concept needed for std::swap_ranges. + // It is mutually convertible, and also SGIAssignable + template + class mutually_convertible_archetype + { + private: + mutually_convertible_archetype() { } + public: + mutually_convertible_archetype(const mutually_convertible_archetype&) { } + mutually_convertible_archetype& + operator=(const mutually_convertible_archetype&) + { return *this; } + mutually_convertible_archetype(boost::detail::dummy_constructor) { } + + template + mutually_convertible_archetype& + operator=(const mutually_convertible_archetype&) + { return *this; } + + }; + int main() { @@ -24,33 +52,22 @@ main() //=========================================================================== // Non-mutating Algorithms { - input_iterator_archetype< convertible_to_archetype< null_archetype > > in; - unary_function_archetype< null_archetype, null_archetype> f; + input_iterator_archetype< + convertible_to_archetype< null_archetype<> > > in; + unary_function_archetype< null_archetype<> , null_archetype<> > + f(dummy_cons); std::for_each(in, in, f); } { - /* - SGI STL Docs and the C++ standard (25.1.2) requirements for - std::for_each() are broken. They should be specified as follows: - - template - InputIterator find(InputIterator first, InputIterator last, - const T& value) - { - function_requires< InputIteratorConcept >(); - typedef typename std::iterator_traits::value_type - value_type; - function_requires< EqualityComparable2 >(); - ... - } - */ - input_iterator_archetype< null_archetype > in; - left_equality_comparable_archetype< null_archetype > value(dummy_cons); + typedef equality_comparable2_first_archetype<> Left; + input_iterator_archetype< Left > in; + equality_comparable2_second_archetype<> value(dummy_cons); in = std::find(in, in, value); } { - input_iterator_archetype< convertible_to_archetype< null_archetype > > in; - unary_predicate_archetype< null_archetype > pred; + input_iterator_archetype< + convertible_to_archetype< null_archetype<> > > in; + unary_predicate_archetype< null_archetype<> > pred(dummy_cons); in = std::find_if(in, in, pred); } { @@ -58,146 +75,447 @@ main() fo = std::adjacent_find(fo, fo); } { - forward_iterator_archetype< convertible_to_archetype< null_archetype > > fo; - binary_predicate_archetype pred; + forward_iterator_archetype< + convertible_to_archetype< null_archetype<> > > fo; + binary_predicate_archetype , null_archetype<> > + pred(dummy_cons); fo = std::adjacent_find(fo, fo, pred); } { - /* SGI STL documentation is wrong. The value type of the - input iterator does not need to be equality comparable. - */ - input_iterator_archetype in; - typedef left_equality_comparable_archetype Right; + typedef equal_op_first_archetype<> Left; + input_iterator_archetype in; + typedef equal_op_second_archetype<> Right; forward_iterator_archetype fo; in = std::find_first_of(in, in, fo, fo); } { - typedef input_iterator_archetype InIter; + typedef equal_op_first_archetype<> Left; + typedef input_iterator_archetype InIter; InIter in; function_requires< InputIteratorConcept >(); - left_equality_comparable_archetype value(dummy_cons); + equal_op_second_archetype<> value(dummy_cons); std::iterator_traits::difference_type n = std::count(in, in, value); ignore_unused_variable_warning(n); } +#if !defined(__KCC) && !defined(BOOST_HIDE_EXPECTED_ERRORS) { - typedef input_iterator_archetype InIter; + typedef equal_op_first_archetype<> Left; + typedef input_iterator_archetype InIter; InIter in; - left_equality_comparable_archetype value(dummy_cons); + equal_op_second_archetype<> value(dummy_cons); unsigned long n; std::count(in, in, value, n); } { - typedef input_iterator_archetype< convertible_to_archetype > InIter; + input_iterator_archetype< convertible_to_archetype > > in; + unary_predicate_archetype > pred; + unsigned long n; + std::count_if(in, in, pred, n); + } +#endif + { + typedef input_iterator_archetype< + convertible_to_archetype > > InIter; InIter in; - unary_predicate_archetype pred; + unary_predicate_archetype > pred(dummy_cons); std::iterator_traits::difference_type n = std::count_if(in, in, pred); ignore_unused_variable_warning(n); } { - input_iterator_archetype< convertible_to_archetype > in; - unary_predicate_archetype pred; - unsigned long n; - std::count_if(in, in, pred, n); - } - { - /* - SGI STL Documentation wrong. EqualityComparable not needed. - */ - typedef input_iterator_archetype InIter1; + typedef equal_op_first_archetype<> Left; + typedef input_iterator_archetype InIter1; InIter1 in1; - typedef left_equality_comparable_archetype Right; + typedef equal_op_second_archetype<> Right; 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; + typedef input_iterator_archetype< + convertible_to_archetype > > InIter; InIter in1, in2; - binary_predicate_archetype pred; + binary_predicate_archetype , null_archetype<> > + pred(dummy_cons); std::pair p = std::mismatch(in1, in1, in2, pred); ignore_unused_variable_warning(p); } { - // SGI STL docs: EqualityComparable not needed - input_iterator_archetype in1; - typedef left_equality_comparable_archetype Right; + typedef equality_comparable2_first_archetype<> Left; + input_iterator_archetype in1; + typedef equality_comparable2_second_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; + input_iterator_archetype< convertible_to_archetype > > + in1, in2; + binary_predicate_archetype , null_archetype<> > + pred(dummy_cons); bool b = std::equal(in1, in1, in2, pred); ignore_unused_variable_warning(b); } { - // SGI STL docs: EqualityComparable not needed - forward_iterator_archetype fo1; - typedef left_equality_comparable_archetype Right; + typedef equality_comparable2_first_archetype<> Left; + forward_iterator_archetype fo1; + typedef equality_comparable2_second_archetype<> Right; forward_iterator_archetype fo2; fo1 = std::search(fo1, fo1, fo2, fo2); } { - // SGI STL docs: LeftEqualityComparable missing - // search() calls find() - typedef convertible_to_archetype Left; + typedef equality_comparable2_first_archetype< + convertible_to_archetype > > Left; forward_iterator_archetype fo1; - typedef convertible_to_archetype > Right; + typedef equality_comparable2_second_archetype< + convertible_to_archetype > > Right; forward_iterator_archetype fo2; - binary_predicate_archetype pred; + binary_predicate_archetype , null_archetype<> > + pred(dummy_cons); fo1 = std::search(fo1, fo1, fo2, fo2, pred); } { - // SGI STL docs: EqualityComparable not needed - forward_iterator_archetype fo; - left_equality_comparable_archetype value(dummy_cons); - int n; + typedef equality_comparable2_first_archetype<> Left; + forward_iterator_archetype fo; + equality_comparable2_second_archetype<> value(dummy_cons); + int n = 1; fo = std::search_n(fo, fo, n, value); } { - // SGI STL docs: EqualityComparable not needed - forward_iterator_archetype< convertible_to_archetype > fo; - convertible_to_archetype value(dummy_cons); - binary_predicate_archetype pred; - int n; + forward_iterator_archetype< + convertible_to_archetype > > fo; + convertible_to_archetype > value(dummy_cons); + binary_predicate_archetype , null_archetype<> > + pred(dummy_cons); + int n = 1; fo = std::search_n(fo, fo, n, value, pred); } { - forward_iterator_archetype fo1; - typedef left_equality_comparable_archetype Right; + typedef equality_comparable2_first_archetype<> Left; + forward_iterator_archetype fo1; + typedef equality_comparable2_second_archetype > Right; forward_iterator_archetype fo2; fo1 = std::find_end(fo1, fo1, fo2, fo2); } { - // SGI STL docs: LeftEqualityComparable missing - typedef convertible_to_archetype Left; + // equality comparable required because find_end() calls search + typedef equality_comparable2_first_archetype< + convertible_to_archetype > > Left; forward_iterator_archetype fo1; - typedef convertible_to_archetype > Right; + typedef equality_comparable2_second_archetype< + convertible_to_archetype > > Right; forward_iterator_archetype fo2; - binary_predicate_archetype pred; + binary_predicate_archetype , null_archetype<> > + pred(dummy_cons); fo1 = std::find_end(fo1, fo1, fo2, fo2, pred); } //=========================================================================== // Mutating Algorithms - // UNDER CONSTRUCTION - { - // SGI STL docs missing CopyConstructible and Assignable - typedef equality_comparable_archetype< copy_constructible_archetype< - assignable_archetype<> > > T; + typedef null_archetype<> OutT; + typedef convertible_to_archetype InT; + input_iterator_archetype in; + output_iterator_archetype out; + out = std::copy(in, in, out); + } +#if !defined(__KCC) + { + // Not in the C++ standard + typedef null_archetype<> OutT; + typedef convertible_to_archetype InT; + input_iterator_archetype in; + output_iterator_archetype out; + int count = 1; + std::pair, + output_iterator_archetype > result = std::copy_n(in, count, out); + ignore_unused_variable_warning(result); + } +#endif + { + typedef assignable_archetype<> OutT; + typedef convertible_to_archetype InT; + bidirectional_iterator_archetype bid_in; + bidirectional_iterator_archetype bid_out; + bid_out = std::copy_backward(bid_in, bid_in, bid_out); + } + { + sgi_assignable_archetype<> a(dummy_cons), b(dummy_cons); + std::swap(a, b); + } + { + typedef sgi_assignable_archetype<> T; + forward_iterator_archetype a, b; + std::iter_swap(a, b); + } + { + typedef mutually_convertible_archetype Tin; + typedef mutually_convertible_archetype Tout; + forward_iterator_archetype fi1; + forward_iterator_archetype fi2; + fi2 = std::swap_ranges(fi1, fi1, fi2); + } + { + typedef convertible_to_archetype > Tin; + typedef null_archetype<> Tout; + input_iterator_archetype in; + output_iterator_archetype out; + unary_function_archetype , + convertible_to_archetype > op(dummy_cons); + out = std::transform(in, in, out, op); + } + { + typedef convertible_to_archetype > Tin1; + typedef convertible_to_archetype > Tin2; + typedef null_archetype<> Tout; + input_iterator_archetype in1; + input_iterator_archetype in2; + output_iterator_archetype out; + binary_function_archetype, null_archetype, + convertible_to_archetype > op(dummy_cons); + out = std::transform(in1, in1, in2, out, op); + } + { + typedef equality_comparable2_first_archetype< + assignable_archetype<> > FT; + forward_iterator_archetype fi; + equality_comparable2_second_archetype< + convertible_to_archetype > value(dummy_cons); + std::replace(fi, fi, value, value); + } + { + typedef null_archetype<> PredArg; + typedef assignable_archetype< + convertible_to_archetype > FT; + forward_iterator_archetype fi; + unary_predicate_archetype pred(dummy_cons); + convertible_to_archetype value(dummy_cons); + std::replace_if(fi, fi, pred, value); + } + { +#if 0 + // Issue, the use of ?: inside replace_copy() complicates things + typedef equal_op_first_archetype<> Tin; + typedef null_archetype<> Tout; + typedef equal_op_second_archetype< convertible_to_archetype > T; + input_iterator_archetype in; + output_iterator_archetype out; + T value(dummy_cons); + out = std::replace_copy(in, in, out, value, value); +#else + typedef null_archetype<> Tout; + typedef equal_op_second_archetype< convertible_to_archetype > T; + // Adding convertible to T for Tin solves the problem, so would + // making T convertible to Tin. Not sure what the right way to + // express the requirement would be. Also, perhaps the + // implementation's use of ?: is invalid. + typedef equal_op_first_archetype< convertible_to_archetype > Tin; + input_iterator_archetype in; + output_iterator_archetype out; + T value(dummy_cons); + out = std::replace_copy(in, in, out, value, value); +#endif + } + { + // The issue of ?: also affects this function + typedef null_archetype PredArg; + typedef null_archetype Tout; + typedef convertible_to_archetype > T; + typedef convertible_to_archetype > > Tin; + input_iterator_archetype in; + output_iterator_archetype out; + unary_predicate_archetype pred(dummy_cons); + T value(dummy_cons); + out = std::replace_copy_if(in, in, out, pred, value); + } + { + typedef assignable_archetype<> FT; + forward_iterator_archetype fi; + typedef convertible_to_archetype T; + T value(dummy_cons); + std::fill(fi, fi, value); + } + { + typedef null_archetype<> Tout; + typedef convertible_to_archetype T; + output_iterator_archetype out; + T value(dummy_cons); + int n = 1; + out = std::fill_n(out, n, value); + } + { + typedef assignable_archetype<> FT; + typedef convertible_to_archetype Ret; + forward_iterator_archetype fi; + generator_archetype gen; + std::generate(fi, fi, gen); + } + { + typedef assignable_archetype<> FT; + typedef convertible_to_archetype Ret; + forward_iterator_archetype fi; + generator_archetype gen; + int n = 1; + std::generate_n(fi, n, gen); + } + { + typedef assignable_archetype< equality_comparable2_first_archetype<> > FT; + typedef equality_comparable2_second_archetype<> T; + forward_iterator_archetype fi; + T value(dummy_cons); + fi = std::remove(fi, fi, value); + } + { + typedef assignable_archetype<> FT; + forward_iterator_archetype fi; + typedef null_archetype<> PredArg; + unary_predicate_archetype pred(dummy_cons); + fi = std::remove_if(fi, fi, pred); + } + { + typedef null_archetype<> Tout; + typedef equality_comparable2_first_archetype< + convertible_to_archetype > Tin; + typedef equality_comparable2_second_archetype<> T; + input_iterator_archetype in; + output_iterator_archetype out; + T value(dummy_cons); + out = std::remove_copy(in, in, out, value); + } + { + typedef null_archetype Tout; + typedef null_archetype PredArg; + typedef convertible_to_archetype > Tin; + input_iterator_archetype in; + output_iterator_archetype out; + unary_predicate_archetype pred(dummy_cons); + out = std::remove_copy_if(in, in, out, pred); + } + { + typedef sgi_assignable_archetype< equality_comparable_archetype<> > T; + forward_iterator_archetype fi; + fi = std::unique(fi, fi); + } + { + typedef null_archetype Arg1; + typedef null_archetype Arg2; + typedef sgi_assignable_archetype< + convertible_to_archetype > > FT; + forward_iterator_archetype fi; + binary_predicate_archetype pred(dummy_cons); + fi = std::unique(fi, fi, pred); + } + { + typedef equality_comparable_archetype< sgi_assignable_archetype<> > T; input_iterator_archetype in; - output_iterator_archetype out; + output_iterator_archetype out; out = std::unique_copy(in, in, out); } - + { + typedef null_archetype Arg1; + typedef null_archetype Arg2; + typedef null_archetype Tout; + typedef sgi_assignable_archetype< + convertible_to_archetype > > > Tin; + input_iterator_archetype in; + output_iterator_archetype out; + binary_predicate_archetype pred(dummy_cons); + out = std::unique_copy(in, in, out, pred); + } + { + typedef sgi_assignable_archetype<> T; + bidirectional_iterator_archetype bi; + std::reverse(bi, bi); + } + { + typedef null_archetype<> Tout; + typedef convertible_to_archetype Tin; + bidirectional_iterator_archetype bi; + output_iterator_archetype out; + out = std::reverse_copy(bi, bi, out); + } + { + typedef sgi_assignable_archetype<> T; + forward_iterator_archetype fi; + // Issue, SGI STL is not have void return type, C++ standard does + std::rotate(fi, fi, fi); + } + { + typedef null_archetype<> Tout; + typedef convertible_to_archetype FT; + forward_iterator_archetype fi; + output_iterator_archetype out; + out = std::rotate_copy(fi, fi, fi, out); + } + { + typedef sgi_assignable_archetype<> T; + random_access_iterator_archetype ri; + std::random_shuffle(ri, ri); + } + { + typedef sgi_assignable_archetype<> T; + random_access_iterator_archetype ri; + unary_function_archetype ran(dummy_cons); + std::random_shuffle(ri, ri, ran); + } +#if !defined(__KCC) + { + typedef assignable_archetype<> Tout; + typedef convertible_to_archetype Tin; + input_iterator_archetype in; + random_access_iterator_archetype ri_out; + ri_out = std::random_sample(in, in, ri_out, ri_out); + } + { + typedef assignable_archetype<> Tout; + typedef convertible_to_archetype Tin; + input_iterator_archetype in; + random_access_iterator_archetype ri_out; + unary_function_archetype ran(dummy_cons); + ri_out = std::random_sample(in, in, ri_out, ri_out, ran); + } + { + typedef assignable_archetype<> Tout; + typedef convertible_to_archetype Tin; + forward_iterator_archetype in; + output_iterator_archetype out; + int n = 1; + out = std::random_sample_n(in, in, out, n); + } + { + typedef assignable_archetype<> Tout; + typedef convertible_to_archetype Tin; + input_iterator_archetype in; + forward_iterator_archetype out; + unary_function_archetype ran(dummy_cons); + int n = 1; + out = std::random_sample_n(in, in, out, n, ran); + } +#endif + { + typedef null_archetype<> PredArg; + typedef sgi_assignable_archetype > FT; + bidirectional_iterator_archetype bi; + unary_predicate_archetype pred(dummy_cons); + bi = std::partition(bi, bi, pred); + } + { + typedef null_archetype<> PredArg; + typedef sgi_assignable_archetype > FT; + forward_iterator_archetype fi; + unary_predicate_archetype pred(dummy_cons); + fi = std::stable_partition(fi, fi, pred); + } //=========================================================================== // Sorting Algorithms