1 // (C) Copyright Jeremy Siek 2000-2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <algorithm>
7 #include <numeric>
8 #include <boost/config.hpp>
9 #include <boost/concept_check.hpp>
10 #include <boost/concept_archetype.hpp>
11
12 /*
13
14 This file uses the archetype classes to find out which concepts
15 actually *cover* the STL algorithms true requirements. The
16 archetypes/concepts chosen do not necessarily match the C++ standard
17 or the SGI STL documentation, but instead were chosen based on the
18 minimal concepts that current STL implementations require, which in
19 many cases is less stringent than the standard. In some places there
20 was significant differences in the implementations' requirements and
21 in those places macros were used to select different requirements,
22 the purpose being to document what the requirements of various
23 implementations are. It is an open issue as to whether the C++
24 standard should be changed to reflect these weaker requirements.
25
26 */
27
28 /**
29 * Input iterator - explanation from Peter Dimov:
30 *
31 * Requirements say that *it is convertible to the value_type, and it is, in
32 * our case. The problem however is that op== is a template and the first
33 * argument fails deduction. std::find is specified in terms of the exact
34 * expression `*it == value`, so if it doesn't compile (and it doesn't),
35 * `find(it, it, value)` won't compile either.
36 *
37 * To address this, the no_proxy variant of the input iterator is used
38 * instead.
39 */
40
41 #define BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE input_iterator_archetype_no_proxy
42
43 boost::detail::dummy_constructor dummy_cons;
44
45 // This is a special concept needed for std::swap_ranges.
46 // It is mutually convertible, and also SGIAssignable
47 template <class T>
48 class mutually_convertible_archetype
49 {
50 private:
mutually_convertible_archetype()51 mutually_convertible_archetype() { }
52 public:
mutually_convertible_archetype(const mutually_convertible_archetype &)53 mutually_convertible_archetype(const mutually_convertible_archetype&) { }
54 mutually_convertible_archetype&
operator =(const mutually_convertible_archetype &)55 operator=(const mutually_convertible_archetype&)
56 { return *this; }
mutually_convertible_archetype(boost::detail::dummy_constructor)57 mutually_convertible_archetype(boost::detail::dummy_constructor) { }
58
59 template <class U>
60 mutually_convertible_archetype&
operator =(const mutually_convertible_archetype<U> &)61 operator=(const mutually_convertible_archetype<U>&)
62 { return *this; }
63
64 };
65
66
67 // for std::accumulate
68 namespace accum
69 {
70 typedef boost::sgi_assignable_archetype<> Ret;
71 struct T {
Taccum::T72 T(const Ret&) { }
Taccum::T73 T(boost::detail::dummy_constructor x) { }
74 };
75 typedef boost::null_archetype<> Tin;
operator +(const T &,const Tin &)76 Ret operator+(const T&, const Tin&) {
77 return Ret(dummy_cons);
78 }
79 }
80
81 // for std::shuffle
82 namespace shuffle
83 {
84 struct URBG {
85 typedef unsigned int result_type;
minshuffle::URBG86 result_type BOOST_CONSTEXPR static min() { return 0; }
maxshuffle::URBG87 result_type BOOST_CONSTEXPR static max() { return 1; }
operator ()shuffle::URBG88 result_type operator()() { return 1; }
89 };
90 }
91
92 // for std::inner_product
93 namespace inner_prod
94 {
95 typedef boost::sgi_assignable_archetype<> RetAdd;
96 typedef boost::sgi_assignable_archetype<> RetMult;
97 struct T {
Tinner_prod::T98 T(const RetAdd&) { }
Tinner_prod::T99 T(boost::detail::dummy_constructor x) { }
100 };
101 typedef boost::null_archetype<int> Tin1;
102 typedef boost::null_archetype<char> Tin2;
103 }
104
105 namespace boost { // so Koenig lookup will find
106
107 inner_prod::RetMult
operator *(const inner_prod::Tin1 &,const inner_prod::Tin2 &)108 operator*(const inner_prod::Tin1&, const inner_prod::Tin2&) {
109 return inner_prod::RetMult(dummy_cons);
110 }
111 inner_prod::RetAdd
operator +(const inner_prod::T &,const inner_prod::RetMult &)112 operator+(const inner_prod::T&,
113 const inner_prod::RetMult&) {
114 return inner_prod::RetAdd(dummy_cons);
115 }
116 }
117
118
119 // for std::partial_sum and adj_diff
120 namespace part_sum
121 {
122 class T {
123 public:
124 typedef boost::sgi_assignable_archetype<> Ret;
T(const Ret &)125 T(const Ret&) { }
T(boost::detail::dummy_constructor x)126 T(boost::detail::dummy_constructor x) { }
127 private:
T()128 T() { }
129 };
operator +(const T &,const T &)130 T::Ret operator+(const T&, const T&) {
131 return T::Ret(dummy_cons);
132 }
operator -(const T &,const T &)133 T::Ret operator-(const T&, const T&) {
134 return T::Ret(dummy_cons);
135 }
136 }
137
138 // for std::power
139
140 namespace power_stuff {
141 struct monoid_archetype {
monoid_archetypepower_stuff::monoid_archetype142 monoid_archetype(boost::detail::dummy_constructor x) { }
143 };
144
145 boost::multipliable_archetype<monoid_archetype>
identity_element(std::multiplies<boost::multipliable_archetype<monoid_archetype>>)146 identity_element
147 (std::multiplies< boost::multipliable_archetype<monoid_archetype> >)
148 {
149 return boost::multipliable_archetype<monoid_archetype>(dummy_cons);
150 }
151 }
152
153 struct tag1 { };
154 struct tag2 { };
155
156
157 int
main()158 main()
159 {
160 using namespace boost;
161
162 //===========================================================================
163 // Non-mutating Algorithms
164 {
165 input_iterator_archetype< null_archetype<> > in;
166 unary_function_archetype< null_archetype<> , null_archetype<> >
167 f(dummy_cons);
168 std::for_each(in, in, f);
169 }
170 // gcc bug
171 {
172 typedef equality_comparable2_first_archetype<> Left;
173 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE< Left > in;
174 equality_comparable2_second_archetype<> value(dummy_cons);
175 in = std::find(in, in, value);
176 }
177 {
178 typedef null_archetype<> T;
179 input_iterator_archetype<T> in;
180 unary_predicate_archetype<T> pred(dummy_cons);
181 in = std::find_if(in, in, pred);
182 }
183 {
184 forward_iterator_archetype< equality_comparable_archetype<> > fo;
185 fo = std::adjacent_find(fo, fo);
186 }
187 {
188 forward_iterator_archetype<
189 convertible_to_archetype< null_archetype<> > > fo;
190 binary_predicate_archetype<null_archetype<> , null_archetype<> >
191 pred(dummy_cons);
192 fo = std::adjacent_find(fo, fo, pred);
193 }
194 // gcc bug
195 {
196 typedef equal_op_first_archetype<> Left;
197 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> in;
198 typedef equal_op_second_archetype<> Right;
199 forward_iterator_archetype<Right> fo;
200 in = std::find_first_of(in, in, fo, fo);
201 }
202 {
203 typedef equal_op_first_archetype<> Left;
204 typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter;
205 InIter in;
206 function_requires< InputIterator<InIter> >();
207 equal_op_second_archetype<> value(dummy_cons);
208 std::iterator_traits<InIter>::difference_type
209 n = std::count(in, in, value);
210 ignore_unused_variable_warning(n);
211 }
212 {
213 typedef input_iterator_archetype< null_archetype<> > InIter;
214 InIter in;
215 unary_predicate_archetype<null_archetype<> > pred(dummy_cons);
216 std::iterator_traits<InIter>::difference_type
217 n = std::count_if(in, in, pred);
218 ignore_unused_variable_warning(n);
219 }
220 // gcc bug
221 {
222 typedef equal_op_first_archetype<> Left;
223 typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> InIter1;
224 InIter1 in1;
225 typedef equal_op_second_archetype<> Right;
226 typedef BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Right> InIter2;
227 InIter2 in2;
228 std::pair<InIter1, InIter2> p = std::mismatch(in1, in1, in2);
229 ignore_unused_variable_warning(p);
230 }
231 {
232 typedef input_iterator_archetype<null_archetype<> > InIter;
233 InIter in1, in2;
234 binary_predicate_archetype<null_archetype<> , null_archetype<> >
235 pred(dummy_cons);
236 std::pair<InIter, InIter> p = std::mismatch(in1, in1, in2, pred);
237 ignore_unused_variable_warning(p);
238 }
239 // gcc bug
240 {
241 typedef equality_comparable2_first_archetype<> Left;
242 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Left> in1;
243 typedef equality_comparable2_second_archetype<> Right;
244 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Right> in2;
245 bool b = std::equal(in1, in1, in2);
246 ignore_unused_variable_warning(b);
247 }
248 {
249 input_iterator_archetype< null_archetype<> >
250 in1, in2;
251 binary_predicate_archetype<null_archetype<> , null_archetype<> >
252 pred(dummy_cons);
253 bool b = std::equal(in1, in1, in2, pred);
254 ignore_unused_variable_warning(b);
255 }
256 {
257 typedef equality_comparable2_first_archetype<> Left;
258 forward_iterator_archetype<Left> fo1;
259 typedef equality_comparable2_second_archetype<> Right;
260 forward_iterator_archetype<Right> fo2;
261 fo1 = std::search(fo1, fo1, fo2, fo2);
262 }
263 {
264 typedef equality_comparable2_first_archetype<
265 convertible_to_archetype<null_archetype<> > > Left;
266 forward_iterator_archetype<Left> fo1;
267 typedef equality_comparable2_second_archetype<
268 convertible_to_archetype<null_archetype<> > > Right;
269 forward_iterator_archetype<Right> fo2;
270 binary_predicate_archetype<null_archetype<> , null_archetype<> >
271 pred(dummy_cons);
272 fo1 = std::search(fo1, fo1, fo2, fo2, pred);
273 }
274 {
275 typedef equality_comparable2_first_archetype<> Left;
276 forward_iterator_archetype<Left> fo;
277 equality_comparable2_second_archetype<> value(dummy_cons);
278 int n = 1;
279 fo = std::search_n(fo, fo, n, value);
280 }
281 {
282 forward_iterator_archetype<
283 convertible_to_archetype<null_archetype<> > > fo;
284 convertible_to_archetype<null_archetype<> > value(dummy_cons);
285 binary_predicate_archetype<null_archetype<> , null_archetype<> >
286 pred(dummy_cons);
287 int n = 1;
288 fo = std::search_n(fo, fo, n, value, pred);
289 }
290 {
291 typedef equality_comparable2_first_archetype<> Left;
292 forward_iterator_archetype<Left> fo1;
293 typedef equality_comparable2_second_archetype<null_archetype<> > Right;
294 forward_iterator_archetype<Right> fo2;
295 fo1 = std::find_end(fo1, fo1, fo2, fo2);
296 }
297 {
298 // equality comparable required because find_end() calls search
299 typedef equality_comparable2_first_archetype<
300 convertible_to_archetype<null_archetype<> > > Left;
301 forward_iterator_archetype<Left> fo1;
302 typedef equality_comparable2_second_archetype<
303 convertible_to_archetype<null_archetype<> > > Right;
304 forward_iterator_archetype<Right> fo2;
305 binary_predicate_archetype<null_archetype<> , null_archetype<> >
306 pred(dummy_cons);
307 fo1 = std::find_end(fo1, fo1, fo2, fo2, pred);
308 }
309
310 //===========================================================================
311 // Mutating Algorithms
312
313 {
314 typedef null_archetype<> T;
315 input_iterator_archetype<T> in;
316 output_iterator_archetype<T> out(dummy_cons);
317 out = std::copy(in, in, out);
318 }
319 {
320 typedef assignable_archetype<> OutT;
321 typedef convertible_to_archetype<OutT> InT;
322 bidirectional_iterator_archetype<InT> bid_in;
323 mutable_bidirectional_iterator_archetype<OutT> bid_out;
324 bid_out = std::copy_backward(bid_in, bid_in, bid_out);
325 }
326 {
327 sgi_assignable_archetype<> a(dummy_cons), b(dummy_cons);
328 std::swap(a, b);
329 }
330 {
331 typedef sgi_assignable_archetype<> T;
332 mutable_forward_iterator_archetype<T> a, b;
333 std::iter_swap(a, b);
334 }
335 #if 0
336 {
337 // fails on gcc 7.3 and clang 6.0
338 typedef mutually_convertible_archetype<int> Tin;
339 typedef mutually_convertible_archetype<char> Tout;
340 mutable_forward_iterator_archetype<Tin> fi1;
341 mutable_forward_iterator_archetype<Tout> fi2;
342 fi2 = std::swap_ranges(fi1, fi1, fi2);
343 }
344 #endif
345 {
346 typedef null_archetype<int> Tin;
347 typedef null_archetype<char> Tout;
348 input_iterator_archetype<Tin> in;
349 output_iterator_archetype<Tout> out(dummy_cons);
350 unary_function_archetype<null_archetype<> ,
351 convertible_to_archetype<Tout> > op(dummy_cons);
352 out = std::transform(in, in, out, op);
353 }
354 {
355 typedef null_archetype<int> Tin1;
356 typedef null_archetype<char> Tin2;
357 typedef null_archetype<double> Tout;
358 input_iterator_archetype<Tin1> in1;
359 input_iterator_archetype<Tin2> in2;
360 output_iterator_archetype<Tout> out(dummy_cons);
361 binary_function_archetype<Tin1, Tin2,
362 convertible_to_archetype<Tout> > op(dummy_cons);
363 out = std::transform(in1, in1, in2, out, op);
364 }
365 {
366 typedef equality_comparable2_first_archetype<
367 assignable_archetype<> > FT;
368 mutable_forward_iterator_archetype<FT> fi;
369 equality_comparable2_second_archetype<
370 convertible_to_archetype<FT> > value(dummy_cons);
371 std::replace(fi, fi, value, value);
372 }
373 {
374 typedef null_archetype<> PredArg;
375 typedef assignable_archetype<
376 convertible_to_archetype<PredArg> > FT;
377 mutable_forward_iterator_archetype<FT> fi;
378 unary_predicate_archetype<PredArg> pred(dummy_cons);
379 convertible_to_archetype<FT> value(dummy_cons);
380 std::replace_if(fi, fi, pred, value);
381 }
382 #if (!defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, > 1900)) && !defined(BOOST_EMBTC)
383 // fails on MSVC 2015 and earlier
384 {
385 // Issue, the use of ?: inside replace_copy() complicates things
386 typedef equal_op_first_archetype<> Tin;
387 typedef null_archetype<> Tout;
388 typedef equal_op_second_archetype< convertible_to_archetype<Tout> > T;
389 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
390 output_iterator_archetype<Tout> out(dummy_cons);
391 T value(dummy_cons);
392 out = std::replace_copy(in, in, out, value, value);
393 }
394 {
395 // The issue of ?: also affects this function
396 typedef null_archetype<> Tout;
397 typedef assignable_archetype< convertible_to_archetype<Tout> > Tin;
398 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
399 output_iterator_archetype<Tout> out(dummy_cons);
400 unary_predicate_archetype<Tin> pred(dummy_cons);
401 Tin value(dummy_cons);
402 out = std::replace_copy_if(in, in, out, pred, value);
403 }
404 #endif
405 {
406 typedef assignable_archetype<> FT;
407 mutable_forward_iterator_archetype<FT> fi;
408 typedef convertible_to_archetype<FT> T;
409 T value(dummy_cons);
410 std::fill(fi, fi, value);
411 }
412 #if !defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
413 // fails on MSVC 2010
414 {
415 typedef null_archetype<> Tout;
416 typedef convertible_to_archetype<Tout> T;
417 output_iterator_archetype<Tout> out(dummy_cons);
418 T value(dummy_cons);
419 int n = 1;
420 out = std::fill_n(out, n, value);
421 }
422 #endif
423 {
424 typedef assignable_archetype<> FT;
425 typedef convertible_to_archetype<FT> Ret;
426 mutable_forward_iterator_archetype<FT> fi;
427 generator_archetype<Ret> gen;
428 std::generate(fi, fi, gen);
429 }
430 {
431 typedef assignable_archetype<> FT;
432 typedef convertible_to_archetype<FT> Ret;
433 mutable_forward_iterator_archetype<FT> fi;
434 generator_archetype<Ret> gen;
435 int n = 1;
436 std::generate_n(fi, n, gen);
437 }
438 {
439 typedef assignable_archetype< equality_comparable2_first_archetype<> > FT;
440 typedef equality_comparable2_second_archetype<> T;
441 mutable_forward_iterator_archetype<FT> fi;
442 T value(dummy_cons);
443 fi = std::remove(fi, fi, value);
444 }
445 {
446 typedef assignable_archetype<> FT;
447 mutable_forward_iterator_archetype<FT> fi;
448 typedef null_archetype<> PredArg;
449 unary_predicate_archetype<PredArg> pred(dummy_cons);
450 fi = std::remove_if(fi, fi, pred);
451 }
452 // gcc bug
453 {
454 typedef null_archetype<> Tout;
455 typedef equality_comparable2_first_archetype<
456 convertible_to_archetype<Tout> > Tin;
457 typedef equality_comparable2_second_archetype<> T;
458 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin> in;
459 output_iterator_archetype<Tout> out(dummy_cons);
460 T value(dummy_cons);
461 out = std::remove_copy(in, in, out, value);
462 }
463 {
464 typedef null_archetype<> T;
465 input_iterator_archetype<T> in;
466 output_iterator_archetype<T> out(dummy_cons);
467 unary_predicate_archetype<T> pred(dummy_cons);
468 out = std::remove_copy_if(in, in, out, pred);
469 }
470 {
471 typedef sgi_assignable_archetype< equality_comparable_archetype<> > T;
472 mutable_forward_iterator_archetype<T> fi;
473 fi = std::unique(fi, fi);
474 }
475 {
476 typedef null_archetype<int> Arg1;
477 typedef null_archetype<char> Arg2;
478 typedef sgi_assignable_archetype<
479 convertible_to_archetype<Arg1,
480 convertible_to_archetype<Arg2> > > FT;
481 mutable_forward_iterator_archetype<FT> fi;
482 binary_predicate_archetype<Arg1, Arg2> pred(dummy_cons);
483 fi = std::unique(fi, fi, pred);
484 }
485 // gcc bug
486 {
487 typedef equality_comparable_archetype< sgi_assignable_archetype<> > T;
488 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<T> in;
489 output_iterator_archetype<T> out(dummy_cons);
490 out = std::unique_copy(in, in, out);
491 }
492 {
493 typedef sgi_assignable_archetype<> T;
494 input_iterator_archetype<T> in;
495 output_iterator_archetype<T> out(dummy_cons);
496 binary_predicate_archetype<T, T> pred(dummy_cons);
497 out = std::unique_copy(in, in, out, pred);
498 }
499 {
500 typedef sgi_assignable_archetype<> T;
501 mutable_bidirectional_iterator_archetype<T> bi;
502 std::reverse(bi, bi);
503 }
504 {
505 typedef null_archetype<> Tout;
506 typedef convertible_to_archetype<Tout> Tin;
507 bidirectional_iterator_archetype<Tin> bi;
508 output_iterator_archetype<Tout> out(dummy_cons);
509 out = std::reverse_copy(bi, bi, out);
510 }
511 {
512 typedef sgi_assignable_archetype<> T;
513 mutable_forward_iterator_archetype<T> fi;
514 // Issue, SGI STL is not have void return type, C++ standard does
515 std::rotate(fi, fi, fi);
516 }
517 {
518 typedef null_archetype<> Tout;
519 typedef convertible_to_archetype<Tout> FT;
520 forward_iterator_archetype<FT> fi;
521 output_iterator_archetype<Tout> out(dummy_cons);
522 out = std::rotate_copy(fi, fi, fi, out);
523 }
524 #ifndef BOOST_NO_CXX98_RANDOM_SHUFFLE
525 {
526 typedef sgi_assignable_archetype<> T;
527 mutable_random_access_iterator_archetype<T> ri;
528 std::random_shuffle(ri, ri);
529 }
530 {
531 typedef sgi_assignable_archetype<> T;
532 mutable_random_access_iterator_archetype<T> ri;
533 unary_function_archetype<std::ptrdiff_t, std::ptrdiff_t> ran(dummy_cons);
534 std::random_shuffle(ri, ri, ran);
535 }
536 #else
537 {
538 typedef sgi_assignable_archetype<> T;
539 mutable_random_access_iterator_archetype<T> ri;
540 shuffle::URBG urbg;
541 std::shuffle(ri, ri, urbg);
542 }
543 #endif
544 {
545 typedef null_archetype<> PredArg;
546 typedef sgi_assignable_archetype<convertible_to_archetype<PredArg> > FT;
547 mutable_bidirectional_iterator_archetype<FT> bi;
548 unary_predicate_archetype<PredArg> pred(dummy_cons);
549 bi = std::partition(bi, bi, pred);
550 }
551 #if !defined(BOOST_MSVC) && !defined(BOOST_EMBTC)
552 {
553 // fails on MSVC
554 typedef null_archetype<> PredArg;
555 typedef sgi_assignable_archetype<convertible_to_archetype<PredArg> > FT;
556 mutable_forward_iterator_archetype<FT> fi;
557 unary_predicate_archetype<PredArg> pred(dummy_cons);
558 fi = std::stable_partition(fi, fi, pred);
559 }
560 #endif
561 //===========================================================================
562 // Sorting Algorithms
563 {
564 typedef sgi_assignable_archetype<
565 less_than_comparable_archetype<> > T;
566 mutable_random_access_iterator_archetype<T> ri;
567 std::sort(ri, ri);
568 }
569 {
570 typedef null_archetype<> Arg;
571 typedef sgi_assignable_archetype<
572 convertible_to_archetype<Arg> > T;
573 mutable_random_access_iterator_archetype<T> ri;
574 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
575 std::sort(ri, ri, comp);
576 }
577 {
578 typedef less_than_comparable_archetype<
579 sgi_assignable_archetype<> > ValueType;
580 mutable_random_access_iterator_archetype<ValueType> ri;
581 std::stable_sort(ri, ri);
582 }
583 {
584 typedef null_archetype<> Arg;
585 typedef sgi_assignable_archetype<
586 convertible_to_archetype<Arg> > ValueType;
587 mutable_random_access_iterator_archetype<ValueType> ri;
588 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
589 std::stable_sort(ri, ri, comp);
590 }
591 {
592 typedef sgi_assignable_archetype<
593 less_than_comparable_archetype<> > T;
594 mutable_random_access_iterator_archetype<T> ri;
595 std::partial_sort(ri, ri, ri);
596 }
597
598 {
599 typedef null_archetype<> Arg;
600 typedef sgi_assignable_archetype<
601 convertible_to_archetype<Arg> > T;
602 mutable_random_access_iterator_archetype<T> ri;
603 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
604 std::partial_sort(ri, ri, ri, comp);
605 }
606 // gcc bug
607 {
608 // This could be formulated so that the two iterators are not
609 // required to have the same value type, but it is messy.
610 typedef sgi_assignable_archetype<
611 less_than_comparable_archetype<> > T;
612 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<T> in;
613 mutable_random_access_iterator_archetype<T> ri_out;
614 ri_out = std::partial_sort_copy(in, in , ri_out, ri_out);
615 }
616 {
617 typedef sgi_assignable_archetype<> T;
618 input_iterator_archetype<T> in;
619 mutable_random_access_iterator_archetype<T> ri_out;
620 binary_predicate_archetype<T, T> comp(dummy_cons);
621 ri_out = std::partial_sort_copy(in, in , ri_out, ri_out, comp);
622 }
623 {
624 typedef sgi_assignable_archetype< less_than_comparable_archetype<> > T;
625 mutable_random_access_iterator_archetype<T> ri;
626 std::nth_element(ri, ri, ri);
627 }
628 {
629 typedef null_archetype<int> Arg1;
630 typedef null_archetype<char> Arg2;
631 typedef sgi_assignable_archetype<
632 convertible_to_archetype<Arg1,
633 convertible_to_archetype<Arg2> > > T;
634 mutable_random_access_iterator_archetype<T> ri;
635 binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
636 std::nth_element(ri, ri, ri, comp);
637 }
638 {
639 #if defined(__KCC)
640 // The KAI version of this uses a one-argument less-than function
641 // object.
642 typedef less_than_comparable_archetype<> T;
643 typedef convertible_to_archetype<T> FT;
644 #else
645 typedef less_than_op_first_archetype<> FT;
646 typedef less_than_op_second_archetype<> T;
647 #endif
648 forward_iterator_archetype<FT> fi;
649 T value(dummy_cons);
650 fi = std::lower_bound(fi, fi, value);
651 }
652 {
653 typedef null_archetype<int> Arg1;
654 typedef null_archetype<char> Arg2;
655 typedef convertible_to_archetype<Arg1> FT;
656 typedef convertible_to_archetype<Arg2> T;
657 forward_iterator_archetype<FT> fi;
658 T value(dummy_cons);
659 binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
660 fi = std::lower_bound(fi, fi, value, comp);
661 }
662 {
663 #if defined(__KCC)
664 typedef less_than_comparable_archetype<> T;
665 typedef convertible_to_archetype<T> FT;
666 #else
667 // Note, order of T,FT is flipped from lower_bound
668 typedef less_than_op_second_archetype<> FT;
669 typedef less_than_op_first_archetype<> T;
670 #endif
671 forward_iterator_archetype<FT> fi;
672 T value(dummy_cons);
673 fi = std::upper_bound(fi, fi, value);
674 }
675 {
676 typedef null_archetype<int> Arg1;
677 typedef null_archetype<char> Arg2;
678 // Note, order of T,FT is flipped from lower_bound
679 typedef convertible_to_archetype<Arg1> T;
680 typedef convertible_to_archetype<Arg2> FT;
681 forward_iterator_archetype<FT> fi;
682 T value(dummy_cons);
683 binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
684 fi = std::upper_bound(fi, fi, value, comp);
685 }
686 #if !defined(BOOST_MSVC) || BOOST_WORKAROUND(BOOST_MSVC, >= 1900)
687 // Fails on MSVC 2013 and earlier
688 {
689 #if defined(__KCC)
690 typedef less_than_comparable_archetype<> T;
691 typedef convertible_to_archetype<T> FT;
692 #else
693 typedef less_than_op_first_archetype<
694 less_than_op_second_archetype< null_archetype<>, optag2>, optag1> FT;
695 typedef less_than_op_second_archetype<
696 less_than_op_first_archetype< null_archetype<>, optag2>, optag1> T;
697 #endif
698 typedef forward_iterator_archetype<FT> FIter;
699 FIter fi;
700 T value(dummy_cons);
701 std::pair<FIter,FIter> p = std::equal_range(fi, fi, value);
702 ignore_unused_variable_warning(p);
703 }
704 #endif
705 {
706 typedef null_archetype<int> Arg1;
707 typedef null_archetype<char> Arg2;
708 typedef convertible_to_archetype<Arg1,
709 convertible_to_archetype<Arg2> > FT;
710 typedef convertible_to_archetype<Arg2,
711 convertible_to_archetype<Arg1> > T;
712 typedef forward_iterator_archetype<FT> FIter;
713 FIter fi;
714 T value(dummy_cons);
715 binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
716 std::pair<FIter,FIter> p = std::equal_range(fi, fi, value, comp);
717 ignore_unused_variable_warning(p);
718 }
719 {
720 #if defined(__KCC)
721 typedef less_than_op_first_archetype< less_than_comparable_archetype<> > T;
722 typedef less_than_op_second_archetype< convertible_to_archetype<T> > FT;
723 #else
724 typedef less_than_op_first_archetype<
725 less_than_op_second_archetype<null_archetype<>, optag2>, optag1> FT;
726 typedef less_than_op_second_archetype<
727 less_than_op_first_archetype<null_archetype<>, optag2>, optag1> T;
728 #endif
729 forward_iterator_archetype<FT> fi;
730 T value(dummy_cons);
731 bool b = std::binary_search(fi, fi, value);
732 ignore_unused_variable_warning(b);
733 }
734 {
735 typedef null_archetype<int> Arg1;
736 typedef null_archetype<char> Arg2;
737 typedef convertible_to_archetype<Arg1,
738 convertible_to_archetype<Arg2> > FT;
739 typedef convertible_to_archetype<Arg2,
740 convertible_to_archetype<Arg1> > T;
741 typedef forward_iterator_archetype<FT> FIter;
742 FIter fi;
743 T value(dummy_cons);
744 binary_predicate_archetype<Arg1, Arg2> comp(dummy_cons);
745 bool b = std::binary_search(fi, fi, value, comp);
746 ignore_unused_variable_warning(b);
747 }
748 {
749 typedef null_archetype<> Tout;
750 typedef less_than_op_first_archetype<
751 less_than_op_second_archetype<
752 convertible_to_archetype<Tout>, optag2>, optag1 > Tin1;
753 typedef less_than_op_second_archetype<
754 less_than_op_first_archetype<
755 convertible_to_archetype<Tout>, optag2> ,optag1> Tin2;
756 // gcc bug
757 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin1> in1;
758 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin2> in2;
759 output_iterator_archetype<Tout> out(dummy_cons);
760 out = std::merge(in1, in1, in2, in2, out);
761 out = std::set_union(in1, in1, in2, in2, out);
762 out = std::set_intersection(in1, in1, in2, in2, out);
763 out = std::set_difference(in1, in1, in2, in2, out);
764 out = std::set_symmetric_difference(in1, in1, in2, in2, out);
765 }
766 {
767 typedef null_archetype<> T;
768 input_iterator_archetype<T> in1;
769 input_iterator_archetype<T,2> in2;
770 output_iterator_archetype<T> out(dummy_cons);
771 binary_predicate_archetype<T, T> comp(dummy_cons);
772 out = std::merge(in1, in1, in2, in2, out, comp);
773 out = std::set_union(in1, in1, in2, in2, out, comp);
774 out = std::set_intersection(in1, in1, in2, in2, out, comp);
775 out = std::set_difference(in1, in1, in2, in2, out, comp);
776 out = std::set_symmetric_difference(in1, in1, in2, in2, out, comp);
777 }
778 {
779 typedef sgi_assignable_archetype<
780 less_than_comparable_archetype<> > T;
781 mutable_bidirectional_iterator_archetype<T> bi;
782 std::inplace_merge(bi, bi, bi);
783 }
784 {
785 typedef null_archetype<> Arg;
786 typedef sgi_assignable_archetype<
787 convertible_to_archetype<Arg> > T;
788 mutable_bidirectional_iterator_archetype<T> bi;
789 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
790 std::inplace_merge(bi, bi, bi, comp);
791 }
792 // gcc bug
793 {
794 typedef less_than_op_first_archetype<
795 less_than_op_second_archetype<null_archetype<>, optag1>, optag2> Tin1;
796 typedef less_than_op_second_archetype<
797 less_than_op_first_archetype<null_archetype<>, optag1>, optag2> Tin2;
798 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin1> in1;
799 BOOST_CONCEPT_CHECK_COMPATIBLE_INPUT_ITERATOR_ARCHETYPE<Tin2> in2;
800 bool b = std::includes(in1, in1, in2, in2);
801 b = std::lexicographical_compare(in1, in1, in2, in2);
802 ignore_unused_variable_warning(b);
803 }
804 {
805 typedef null_archetype<int> Tin;
806 input_iterator_archetype<Tin> in1;
807 input_iterator_archetype<Tin,1> in2;
808 binary_predicate_archetype<Tin, Tin> comp(dummy_cons);
809 bool b = std::includes(in1, in1, in2, in2, comp);
810 b = std::lexicographical_compare(in1, in1, in2, in2, comp);
811 ignore_unused_variable_warning(b);
812 }
813 {
814 typedef sgi_assignable_archetype<
815 less_than_comparable_archetype<> > T;
816 mutable_random_access_iterator_archetype<T> ri;
817 std::push_heap(ri, ri);
818 std::pop_heap(ri, ri);
819 std::make_heap(ri, ri);
820 std::sort_heap(ri, ri);
821 }
822 {
823 typedef null_archetype<> Arg;
824 typedef sgi_assignable_archetype<
825 convertible_to_archetype<Arg> > T;
826 mutable_random_access_iterator_archetype<T> ri;
827 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
828 std::push_heap(ri, ri, comp);
829 std::pop_heap(ri, ri, comp);
830 std::make_heap(ri, ri, comp);
831 std::sort_heap(ri, ri, comp);
832 }
833 {
834 typedef less_than_comparable_archetype<> T;
835 T a(dummy_cons), b(dummy_cons);
836 BOOST_USING_STD_MIN();
837 BOOST_USING_STD_MAX();
838 const T& c = min BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
839 const T& d = max BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
840 ignore_unused_variable_warning(c);
841 ignore_unused_variable_warning(d);
842 }
843 {
844 typedef null_archetype<> Arg;
845 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
846 typedef convertible_to_archetype<Arg> T;
847 T a(dummy_cons), b(dummy_cons);
848 BOOST_USING_STD_MIN();
849 BOOST_USING_STD_MAX();
850 const T& c = min BOOST_PREVENT_MACRO_SUBSTITUTION(a, b, comp);
851 const T& d = max BOOST_PREVENT_MACRO_SUBSTITUTION(a, b, comp);
852 ignore_unused_variable_warning(c);
853 ignore_unused_variable_warning(d);
854 }
855 {
856 typedef less_than_comparable_archetype<> T;
857 forward_iterator_archetype<T> fi;
858 fi = std::min_element(fi, fi);
859 fi = std::max_element(fi, fi);
860 }
861 {
862 typedef null_archetype<> Arg;
863 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
864 typedef convertible_to_archetype<Arg> T;
865 forward_iterator_archetype<T> fi;
866 fi = std::min_element(fi, fi, comp);
867 fi = std::max_element(fi, fi, comp);
868 }
869 {
870 typedef sgi_assignable_archetype<
871 less_than_comparable_archetype<> > T;
872 mutable_bidirectional_iterator_archetype<T> bi;
873 bool b = std::next_permutation(bi, bi);
874 b = std::prev_permutation(bi, bi);
875 ignore_unused_variable_warning(b);
876 }
877 {
878 typedef null_archetype<> Arg;
879 binary_predicate_archetype<Arg, Arg> comp(dummy_cons);
880 typedef sgi_assignable_archetype<
881 convertible_to_archetype<Arg> > T;
882 mutable_bidirectional_iterator_archetype<T> bi;
883 bool b = std::next_permutation(bi, bi, comp);
884 b = std::prev_permutation(bi, bi, comp);
885 ignore_unused_variable_warning(b);
886 }
887 //===========================================================================
888 // Generalized Numeric Algorithms
889
890 {
891 // Bummer, couldn't use plus_op because of a problem with
892 // mutually recursive types.
893 input_iterator_archetype<accum::Tin> in;
894 accum::T init(dummy_cons);
895 init = std::accumulate(in, in, init);
896 }
897 {
898 typedef null_archetype<int> Arg1;
899 typedef null_archetype<char> Arg2;
900 typedef sgi_assignable_archetype<
901 convertible_to_archetype<Arg1> > T;
902 typedef convertible_to_archetype<T> Ret;
903 input_iterator_archetype<Arg2> in;
904 T init(dummy_cons);
905 binary_function_archetype<Arg1, Arg2, Ret> op(dummy_cons);
906 init = std::accumulate(in, in, init, op);
907 }
908 {
909 input_iterator_archetype<inner_prod::Tin1> in1;
910 input_iterator_archetype<inner_prod::Tin2> in2;
911 inner_prod::T init(dummy_cons);
912 init = std::inner_product(in1, in1, in2, init);
913 }
914 {
915 typedef null_archetype<int> MultArg1;
916 typedef null_archetype<char> MultArg2;
917 typedef null_archetype<short> AddArg1;
918 typedef null_archetype<long> AddArg2;
919 typedef sgi_assignable_archetype<
920 convertible_to_archetype<AddArg1> > T;
921 typedef convertible_to_archetype<AddArg2> RetMult;
922 typedef convertible_to_archetype<T> RetAdd;
923 input_iterator_archetype<MultArg1> in1;
924 input_iterator_archetype<MultArg2> in2;
925 T init(dummy_cons);
926 binary_function_archetype<MultArg1, MultArg2, RetMult> mult_op(dummy_cons);
927 binary_function_archetype<AddArg1, AddArg2, RetAdd> add_op(dummy_cons);
928 init = std::inner_product(in1, in1, in2, init, add_op, mult_op);
929 }
930 {
931 input_iterator_archetype<part_sum::T> in;
932 output_iterator_archetype<part_sum::T> out(dummy_cons);
933 out = std::partial_sum(in, in, out);
934 }
935 {
936 typedef sgi_assignable_archetype<> T;
937 input_iterator_archetype<T> in;
938 output_iterator_archetype<T> out(dummy_cons);
939 binary_function_archetype<T, T, T> add_op(dummy_cons);
940 out = std::partial_sum(in, in, out, add_op);
941 binary_function_archetype<T, T, T> subtract_op(dummy_cons);
942 out = std::adjacent_difference(in, in, out, subtract_op);
943 }
944 {
945 input_iterator_archetype<part_sum::T> in;
946 output_iterator_archetype<part_sum::T> out(dummy_cons);
947 out = std::adjacent_difference(in, in, out);
948 }
949 return 0;
950 }
951