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