source: NonGTP/Boost/boost/concept_check.hpp @ 857

Revision 857, 34.4 KB checked in by igarcia, 19 years ago (diff)
Line 
1//
2// (C) Copyright Jeremy Siek 2000.
3// Distributed under the Boost Software License, Version 1.0. (See
4// accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6//
7// Revision History:
8//   05 May   2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek)
9//   02 April 2001: Removed limits header altogether. (Jeremy Siek)
10//   01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
11//
12
13// See http://www.boost.org/libs/concept_check for documentation.
14
15#ifndef BOOST_CONCEPT_CHECKS_HPP
16#define BOOST_CONCEPT_CHECKS_HPP
17
18#include <boost/config.hpp>
19#include <boost/iterator.hpp>
20#include <boost/type_traits/conversion_traits.hpp>
21#include <utility>
22#include <boost/type_traits/conversion_traits.hpp>
23#include <boost/static_assert.hpp>
24#include <boost/mpl/identity.hpp>
25
26
27#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__BORLANDC__)
28#define BOOST_FPTR
29#else
30#define BOOST_FPTR &
31#endif
32
33namespace boost {
34
35/*
36  "inline" is used for ignore_unused_variable_warning()
37   and function_requires() to make sure there is no
38   overhead with g++.
39 */
40
41template <class T> inline void ignore_unused_variable_warning(const T&) { }
42
43// the unused, defaulted parameter is a workaround for MSVC and Compaq C++
44template <class Concept>
45inline void function_requires(mpl::identity<Concept>* = 0)
46{
47#if !defined(NDEBUG)
48  void (Concept::*x)() = BOOST_FPTR Concept::constraints;
49  ignore_unused_variable_warning(x);
50#endif
51}
52
53#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
54  typedef void (ns::concept <type_var>::* func##type_var##concept)(); \
55  template <func##type_var##concept Tp1_> \
56  struct concept_checking_##type_var##concept { }; \
57  typedef concept_checking_##type_var##concept< \
58    BOOST_FPTR ns::concept<type_var>::constraints> \
59    concept_checking_typedef_##type_var##concept
60
61#define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \
62  typedef void (ns::concept <type_var1,type_var2>::* \
63     func##type_var1##type_var2##concept)(); \
64  template <func##type_var1##type_var2##concept Tp1_> \
65  struct concept_checking_##type_var1##type_var2##concept { }; \
66  typedef concept_checking_##type_var1##type_var2##concept< \
67    BOOST_FPTR ns::concept<type_var1,type_var2>::constraints> \
68    concept_checking_typedef_##type_var1##type_var2##concept
69
70#define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \
71  typedef void (ns::concept <tv1,tv2,tv3>::* \
72     func##tv1##tv2##tv3##concept)(); \
73  template <func##tv1##tv2##tv3##concept Tp1_> \
74  struct concept_checking_##tv1##tv2##tv3##concept { }; \
75  typedef concept_checking_##tv1##tv2##tv3##concept< \
76    BOOST_FPTR ns::concept<tv1,tv2,tv3>::constraints> \
77    concept_checking_typedef_##tv1##tv2##tv3##concept
78
79#define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \
80  typedef void (ns::concept <tv1,tv2,tv3,tv4>::* \
81     func##tv1##tv2##tv3##tv4##concept)(); \
82  template <func##tv1##tv2##tv3##tv4##concept Tp1_> \
83  struct concept_checking_##tv1##tv2##tv3##tv4##concept { }; \
84  typedef concept_checking_##tv1##tv2##tv3##tv4##concept< \
85    BOOST_FPTR ns::concept<tv1,tv2,tv3,tv4>::constraints> \
86    concept_checking_typedef_##tv1##tv2##tv3##tv4##concept
87
88// NOTE: The BOOST_CLASS_REQUIRES (with an 'S' at the end) is deprecated.
89
90// The BOOST_CLASS_REQUIRES macros use function pointers as
91// template parameters, which VC++ does not support.
92
93#if defined(BOOST_NO_FUNCTION_PTR_TEMPLATE_PARAMETERS)
94
95#define BOOST_CLASS_REQUIRES(type_var, concept)
96#define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept)
97#define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept)
98#define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept)
99
100#else
101
102#define BOOST_CLASS_REQUIRES(type_var, concept) \
103  typedef void (concept <type_var>::* func##type_var##concept)(); \
104  template <func##type_var##concept Tp1_> \
105  struct concept_checking_##type_var##concept { }; \
106  typedef concept_checking_##type_var##concept< \
107    BOOST_FPTR concept <type_var>::constraints> \
108    concept_checking_typedef_##type_var##concept
109
110#define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept) \
111  typedef void (concept <type_var1,type_var2>::* func##type_var1##type_var2##concept)(); \
112  template <func##type_var1##type_var2##concept Tp1_> \
113  struct concept_checking_##type_var1##type_var2##concept { }; \
114  typedef concept_checking_##type_var1##type_var2##concept< \
115    BOOST_FPTR concept <type_var1,type_var2>::constraints> \
116    concept_checking_typedef_##type_var1##type_var2##concept
117
118#define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept) \
119  typedef void (concept <type_var1,type_var2,type_var3>::* func##type_var1##type_var2##type_var3##concept)(); \
120  template <func##type_var1##type_var2##type_var3##concept Tp1_> \
121  struct concept_checking_##type_var1##type_var2##type_var3##concept { }; \
122  typedef concept_checking_##type_var1##type_var2##type_var3##concept< \
123    BOOST_FPTR concept <type_var1,type_var2,type_var3>::constraints>  \
124  concept_checking_typedef_##type_var1##type_var2##type_var3##concept
125
126#define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept) \
127  typedef void (concept <type_var1,type_var2,type_var3,type_var4>::* func##type_var1##type_var2##type_var3##type_var4##concept)(); \
128  template <func##type_var1##type_var2##type_var3##type_var4##concept Tp1_> \
129  struct concept_checking_##type_var1##type_var2##type_var3##type_var4##concept { }; \
130  typedef concept_checking_##type_var1##type_var2##type_var3##type_var4##concept< \
131    BOOST_FPTR concept <type_var1,type_var2,type_var3,type_var4>::constraints>  \
132    concept_checking_typedef_##type_var1##type_var2##type_var3##type_var4##concept
133
134
135#endif
136
137#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
138template <class T, class U>
139struct require_same { };
140
141template <class T>
142struct require_same<T,T> { typedef T type; };
143#else
144// This version does not perform checking, but will not do any harm.
145template <class T, class U>
146struct require_same { typedef T type; };
147#endif
148
149  template <class T>
150  struct IntegerConcept {
151    void constraints() {
152#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
153      x.error_type_must_be_an_integer_type();
154#endif     
155    }
156    T x;
157  };
158#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
159  template <> struct IntegerConcept<short> { void constraints() {} };
160  template <> struct IntegerConcept<unsigned short> { void constraints() {} };
161  template <> struct IntegerConcept<int> { void constraints() {} };
162  template <> struct IntegerConcept<unsigned int> { void constraints() {} };
163  template <> struct IntegerConcept<long> { void constraints() {} };
164  template <> struct IntegerConcept<unsigned long> { void constraints() {} };
165  // etc.
166#endif     
167
168  template <class T>
169  struct SignedIntegerConcept {
170    void constraints() {
171#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
172      x.error_type_must_be_a_signed_integer_type();
173#endif     
174    }
175    T x;
176  };
177#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
178  template <> struct SignedIntegerConcept<short> { void constraints() {} };
179  template <> struct SignedIntegerConcept<int> { void constraints() {} };
180  template <> struct SignedIntegerConcept<long> { void constraints() {} };
181# if defined(BOOST_HAS_LONG_LONG)
182  template <> struct SignedIntegerConcept< ::boost::long_long_type> { void constraints() {} };
183# endif
184  // etc.
185#endif     
186
187  template <class T>
188  struct UnsignedIntegerConcept {
189    void constraints() {
190#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
191      x.error_type_must_be_an_unsigned_integer_type();
192#endif     
193    }
194    T x;
195  };
196#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
197  template <> struct UnsignedIntegerConcept<unsigned short>
198    { void constraints() {} };
199  template <> struct UnsignedIntegerConcept<unsigned int>
200    { void constraints() {} };
201  template <> struct UnsignedIntegerConcept<unsigned long>
202    { void constraints() {} };
203  // etc.
204#endif     
205
206  //===========================================================================
207  // Basic Concepts
208
209  template <class TT>
210  struct DefaultConstructibleConcept
211  {
212    void constraints() {
213      TT a;               // require default constructor
214      ignore_unused_variable_warning(a);
215    }
216  };
217
218  template <class TT>
219  struct AssignableConcept
220  {
221    void constraints() {
222#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
223      a = a;              // require assignment operator
224#endif
225      const_constraints(a);
226    }
227    void const_constraints(const TT& b) {
228#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
229      a = b;              // const required for argument to assignment
230#endif
231    }
232    TT a;
233  };
234
235  template <class TT>
236  struct CopyConstructibleConcept
237  {
238    void constraints() {
239      TT a(b);            // require copy constructor
240      TT* ptr = &a;       // require address of operator
241      const_constraints(a);
242      ignore_unused_variable_warning(ptr);
243    }
244    void const_constraints(const TT& a) {
245      TT c(a);            // require const copy constructor
246      const TT* ptr = &a; // require const address of operator
247      ignore_unused_variable_warning(c);
248      ignore_unused_variable_warning(ptr);
249    }
250    TT b;
251  };
252
253  // The SGI STL version of Assignable requires copy constructor and operator=
254  template <class TT>
255  struct SGIAssignableConcept
256  {
257    void constraints() {
258      TT b(a);
259#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
260      a = a;              // require assignment operator
261#endif
262      const_constraints(a);
263      ignore_unused_variable_warning(b);
264    }
265    void const_constraints(const TT& b) {
266      TT c(b);
267#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
268      a = b;              // const required for argument to assignment
269#endif
270      ignore_unused_variable_warning(c);
271    }
272    TT a;
273  };
274
275  template <class X, class Y>
276  struct ConvertibleConcept
277  {
278    void constraints() {
279      Y y = x;
280      ignore_unused_variable_warning(y);
281    }
282    X x;
283  };
284
285  // The C++ standard requirements for many concepts talk about return
286  // types that must be "convertible to bool".  The problem with this
287  // requirement is that it leaves the door open for evil proxies that
288  // define things like operator|| with strange return types.  Two
289  // possible solutions are:
290  // 1) require the return type to be exactly bool
291  // 2) stay with convertible to bool, and also
292  //    specify stuff about all the logical operators.
293  // For now we just test for convertible to bool.
294  template <class TT>
295  void require_boolean_expr(const TT& t) {
296    bool x = t;
297    ignore_unused_variable_warning(x);
298  }
299
300  template <class TT>
301  struct EqualityComparableConcept
302  {
303    void constraints() {
304      require_boolean_expr(a == b);
305      require_boolean_expr(a != b);
306    }
307    TT a, b;
308  };
309
310  template <class TT>
311  struct LessThanComparableConcept
312  {
313    void constraints() {
314      require_boolean_expr(a < b);
315    }
316    TT a, b;
317  };
318
319  // This is equivalent to SGI STL's LessThanComparable.
320  template <class TT>
321  struct ComparableConcept
322  {
323    void constraints() {
324      require_boolean_expr(a < b);
325      require_boolean_expr(a > b);
326      require_boolean_expr(a <= b);
327      require_boolean_expr(a >= b);
328    }
329    TT a, b;
330  };
331
332#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
333  template <class First, class Second> \
334  struct NAME { \
335    void constraints() { (void)constraints_(); } \
336    bool constraints_() {  \
337      return  a OP b; \
338    } \
339    First a; \
340    Second b; \
341  }
342
343#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
344  template <class Ret, class First, class Second> \
345  struct NAME { \
346    void constraints() { (void)constraints_(); } \
347    Ret constraints_() {  \
348      return a OP b; \
349    } \
350    First a; \
351    Second b; \
352  }
353
354  BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept);
355  BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOpConcept);
356  BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOpConcept);
357  BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOpConcept);
358  BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOpConcept);
359  BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOpConcept);
360
361  BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOpConcept);
362  BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOpConcept);
363  BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOpConcept);
364  BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOpConcept);
365  BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOpConcept);
366
367  //===========================================================================
368  // Function Object Concepts
369
370  template <class Func, class Return>
371  struct GeneratorConcept
372  {
373    void constraints() {
374      const Return& r = f();   // require operator() member function
375      ignore_unused_variable_warning(r);
376    }
377    Func f;
378  };
379
380
381#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
382  template <class Func>
383  struct GeneratorConcept<Func,void>
384  {
385    void constraints() {
386      f();              // require operator() member function
387    }
388    Func f;
389  };
390#endif
391
392  template <class Func, class Return, class Arg>
393  struct UnaryFunctionConcept
394  {
395    // required in case any of our template args are const-qualified:
396    UnaryFunctionConcept();
397   
398    void constraints() {
399      r = f(arg); // require operator()
400    }
401    Func f;
402    Arg arg;
403    Return r;
404  };
405
406#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
407  template <class Func, class Arg>
408  struct UnaryFunctionConcept<Func, void, Arg> {
409    void constraints() {
410      f(arg);                 // require operator()
411    }
412    Func f;
413    Arg arg;
414  };
415#endif
416
417  template <class Func, class Return, class First, class Second>
418  struct BinaryFunctionConcept
419  {
420    void constraints() {
421      r = f(first, second); // require operator()
422    }
423    Func f;
424    First first;
425    Second second;
426    Return r;
427  };
428
429#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
430  template <class Func, class First, class Second>
431  struct BinaryFunctionConcept<Func, void, First, Second>
432  {
433    void constraints() {
434      f(first, second); // require operator()
435    }
436    Func f;
437    First first;
438    Second second;
439  };
440#endif
441
442  template <class Func, class Arg>
443  struct UnaryPredicateConcept
444  {
445    void constraints() {
446      require_boolean_expr(f(arg)); // require operator() returning bool
447    }
448    Func f;
449    Arg arg;
450  };
451
452  template <class Func, class First, class Second>
453  struct BinaryPredicateConcept
454  {
455    void constraints() {
456      require_boolean_expr(f(a, b)); // require operator() returning bool
457    }
458    Func f;
459    First a;
460    Second b;
461  };
462
463  // use this when functor is used inside a container class like std::set
464  template <class Func, class First, class Second>
465  struct Const_BinaryPredicateConcept {
466    void constraints() {
467      const_constraints(f);
468    }
469    void const_constraints(const Func& fun) {
470      function_requires<BinaryPredicateConcept<Func, First, Second> >();
471      // operator() must be a const member function
472      require_boolean_expr(fun(a, b));
473    }
474    Func f;
475    First a;
476    Second b;
477  };
478
479  template <class Func, class Return>
480  struct AdaptableGeneratorConcept
481  {
482    void constraints() {
483      typedef typename Func::result_type result_type;
484      BOOST_STATIC_ASSERT((is_convertible<result_type, Return>::value));
485      function_requires< GeneratorConcept<Func, result_type> >();
486    }
487  };
488
489  template <class Func, class Return, class Arg>
490  struct AdaptableUnaryFunctionConcept
491  {
492    void constraints() {
493      typedef typename Func::argument_type argument_type;
494      typedef typename Func::result_type result_type;
495      BOOST_STATIC_ASSERT((is_convertible<result_type, Return>::value));
496      BOOST_STATIC_ASSERT((is_convertible<Arg, argument_type>::value));
497      function_requires< UnaryFunctionConcept<Func, result_type, argument_type> >();
498    }
499  };
500
501  template <class Func, class Return, class First, class Second>
502  struct AdaptableBinaryFunctionConcept
503  {
504    void constraints() {
505      typedef typename Func::first_argument_type first_argument_type;
506      typedef typename Func::second_argument_type second_argument_type;
507      typedef typename Func::result_type result_type;
508      BOOST_STATIC_ASSERT((is_convertible<result_type, Return>::value));
509      BOOST_STATIC_ASSERT((is_convertible<First, first_argument_type>::value));
510      BOOST_STATIC_ASSERT((is_convertible<Second, second_argument_type>::value));
511      function_requires< BinaryFunctionConcept<Func, result_type,
512        first_argument_type, second_argument_type> >();
513    }
514  };
515
516  template <class Func, class Arg>
517  struct AdaptablePredicateConcept
518  {
519    void constraints() {
520      function_requires< UnaryPredicateConcept<Func, Arg> >();
521      function_requires< AdaptableUnaryFunctionConcept<Func, bool, Arg> >();
522    }
523  };
524
525  template <class Func, class First, class Second>
526  struct AdaptableBinaryPredicateConcept
527  {
528    void constraints() {
529      function_requires< BinaryPredicateConcept<Func, First, Second> >();
530      function_requires< AdaptableBinaryFunctionConcept<Func, bool, First, Second> >();
531    }
532  };
533
534  //===========================================================================
535  // Iterator Concepts
536
537  template <class TT>
538  struct InputIteratorConcept
539  {
540    void constraints() {
541      function_requires< AssignableConcept<TT> >();
542      function_requires< EqualityComparableConcept<TT> >();
543      TT j(i);
544      (void)*i;           // require dereference operator
545#ifndef BOOST_NO_STD_ITERATOR_TRAITS
546      // require iterator_traits typedef's
547      typedef typename std::iterator_traits<TT>::difference_type D;
548      // Hmm, the following is a bit fragile
549      //function_requires< SignedIntegerConcept<D> >();
550      typedef typename std::iterator_traits<TT>::reference R;
551      typedef typename std::iterator_traits<TT>::pointer P;
552      typedef typename std::iterator_traits<TT>::iterator_category C;
553      function_requires< ConvertibleConcept<C, std::input_iterator_tag> >();
554#endif
555      ++j;                // require preincrement operator
556      i++;                // require postincrement operator
557    }
558    TT i;
559  };
560
561  template <class TT, class ValueT>
562  struct OutputIteratorConcept
563  {
564    void constraints() {
565      function_requires< AssignableConcept<TT> >();
566      ++i;                // require preincrement operator
567      i++;                // require postincrement operator
568      *i++ = t;           // require postincrement and assignment
569    }
570    TT i, j;
571    ValueT t;
572  };
573
574  template <class TT>
575  struct ForwardIteratorConcept
576  {
577    void constraints() {
578      function_requires< InputIteratorConcept<TT> >();
579#ifndef BOOST_NO_STD_ITERATOR_TRAITS
580      typedef typename std::iterator_traits<TT>::iterator_category C;
581      function_requires< ConvertibleConcept<C, std::forward_iterator_tag> >();
582      typedef typename std::iterator_traits<TT>::reference reference;
583      reference r = *i;
584      ignore_unused_variable_warning(r);
585#endif
586    }
587    TT i;
588  };
589
590  template <class TT>
591  struct Mutable_ForwardIteratorConcept
592  {
593    void constraints() {
594      function_requires< ForwardIteratorConcept<TT> >();
595      *i++ = *i;         // require postincrement and assignment
596    }
597    TT i;
598  };
599
600  template <class TT>
601  struct BidirectionalIteratorConcept
602  {
603    void constraints() {
604      function_requires< ForwardIteratorConcept<TT> >();
605#ifndef BOOST_NO_STD_ITERATOR_TRAITS
606      typedef typename std::iterator_traits<TT>::iterator_category C;
607      function_requires< ConvertibleConcept<C,
608        std::bidirectional_iterator_tag> >();
609#endif
610      --i;                // require predecrement operator
611      i--;                // require postdecrement operator
612    }
613    TT i;
614  };
615
616  template <class TT>
617  struct Mutable_BidirectionalIteratorConcept
618  {
619    void constraints() {
620      function_requires< BidirectionalIteratorConcept<TT> >();
621      function_requires< Mutable_ForwardIteratorConcept<TT> >();
622      *i-- = *i;                  // require postdecrement and assignment
623    }
624    TT i;
625  };
626
627
628  template <class TT>
629  struct RandomAccessIteratorConcept
630  {
631    void constraints() {
632      function_requires< BidirectionalIteratorConcept<TT> >();
633      function_requires< ComparableConcept<TT> >();
634#ifndef BOOST_NO_STD_ITERATOR_TRAITS
635      typedef typename std::iterator_traits<TT>::iterator_category C;
636      function_requires< ConvertibleConcept< C,
637        std::random_access_iterator_tag> >();
638      typedef typename std::iterator_traits<TT>::reference R;
639#endif
640
641      i += n;             // require assignment addition operator
642      i = i + n; i = n + i; // require addition with difference type
643      i -= n;             // require assignment subtraction operator
644      i = i - n;                  // require subtraction with difference type
645      n = i - j;                  // require difference operator
646      (void)i[n];                 // require element access operator
647    }
648    TT a, b;
649    TT i, j;
650#ifndef BOOST_NO_STD_ITERATOR_TRAITS
651    typename std::iterator_traits<TT>::difference_type n;
652#else
653    std::ptrdiff_t n;
654#endif
655  };
656
657  template <class TT>
658  struct Mutable_RandomAccessIteratorConcept
659  {
660    void constraints() {
661      function_requires< RandomAccessIteratorConcept<TT> >();
662      function_requires< Mutable_BidirectionalIteratorConcept<TT> >();
663      i[n] = *i;                  // require element access and assignment
664    }
665    TT i;
666#ifndef BOOST_NO_STD_ITERATOR_TRAITS
667    typename std::iterator_traits<TT>::difference_type n;
668#else
669    std::ptrdiff_t n;
670#endif
671  };
672
673  //===========================================================================
674  // Container Concepts
675
676  template <class Container>
677  struct ContainerConcept
678  {
679    typedef typename Container::value_type value_type;
680    typedef typename Container::difference_type difference_type;
681    typedef typename Container::size_type size_type;
682    typedef typename Container::const_reference const_reference;
683    typedef typename Container::const_pointer const_pointer;
684    typedef typename Container::const_iterator const_iterator;
685
686    void constraints() {
687      function_requires< InputIteratorConcept<const_iterator> >();
688      function_requires< AssignableConcept<Container> >();
689      const_constraints(c);
690    }
691    void const_constraints(const Container& cc) {
692      i = cc.begin();
693      i = cc.end();
694      n = cc.size();
695      n = cc.max_size();
696      b = cc.empty();
697    }
698    Container c;
699    bool b;
700    const_iterator i;
701    size_type n;
702  };
703
704  template <class Container>
705  struct Mutable_ContainerConcept
706  {
707    typedef typename Container::value_type value_type;
708    typedef typename Container::reference reference;
709    typedef typename Container::iterator iterator;
710    typedef typename Container::pointer pointer;
711   
712    void constraints() {
713      function_requires< ContainerConcept<Container> >();
714      function_requires< AssignableConcept<value_type> >();
715      function_requires< InputIteratorConcept<iterator> >();
716
717      i = c.begin();
718      i = c.end();
719      c.swap(c2);
720    }
721    iterator i;
722    Container c, c2;
723  };
724
725  template <class ForwardContainer>
726  struct ForwardContainerConcept
727  {
728    void constraints() {
729      function_requires< ContainerConcept<ForwardContainer> >();
730      typedef typename ForwardContainer::const_iterator const_iterator;
731      function_requires< ForwardIteratorConcept<const_iterator> >();
732    }
733  }; 
734
735  template <class ForwardContainer>
736  struct Mutable_ForwardContainerConcept
737  {
738    void constraints() {
739      function_requires< ForwardContainerConcept<ForwardContainer> >();
740      function_requires< Mutable_ContainerConcept<ForwardContainer> >();
741      typedef typename ForwardContainer::iterator iterator;
742      function_requires< Mutable_ForwardIteratorConcept<iterator> >();
743    }
744  }; 
745
746  template <class ReversibleContainer>
747  struct ReversibleContainerConcept
748  {
749    typedef typename ReversibleContainer::const_iterator const_iterator;
750    typedef typename ReversibleContainer::const_reverse_iterator
751      const_reverse_iterator;
752
753    void constraints() {
754      function_requires< ForwardContainerConcept<ReversibleContainer> >();
755      function_requires< BidirectionalIteratorConcept<const_iterator> >();
756      function_requires<
757        BidirectionalIteratorConcept<const_reverse_iterator> >();
758      const_constraints(c);
759    }
760    void const_constraints(const ReversibleContainer& cc) {
761      const_reverse_iterator i = cc.rbegin();
762      i = cc.rend();
763    }
764    ReversibleContainer c;
765  };
766
767  template <class ReversibleContainer>
768  struct Mutable_ReversibleContainerConcept
769  {
770    typedef typename ReversibleContainer::iterator iterator;
771    typedef typename ReversibleContainer::reverse_iterator reverse_iterator;
772
773    void constraints() {
774      function_requires< ReversibleContainerConcept<ReversibleContainer> >();
775      function_requires<
776        Mutable_ForwardContainerConcept<ReversibleContainer> >();
777      function_requires< Mutable_BidirectionalIteratorConcept<iterator> >();
778      function_requires<
779        Mutable_BidirectionalIteratorConcept<reverse_iterator> >();
780
781      reverse_iterator i = c.rbegin();
782      i = c.rend();
783    }
784    ReversibleContainer c;
785  };
786
787  template <class RandomAccessContainer>
788  struct RandomAccessContainerConcept
789  {
790    typedef typename RandomAccessContainer::size_type size_type;
791    typedef typename RandomAccessContainer::const_reference const_reference;
792    typedef typename RandomAccessContainer::const_iterator const_iterator;
793    typedef typename RandomAccessContainer::const_reverse_iterator
794      const_reverse_iterator;
795
796    void constraints() {
797      function_requires< ReversibleContainerConcept<RandomAccessContainer> >();
798      function_requires< RandomAccessIteratorConcept<const_iterator> >();
799      function_requires<
800        RandomAccessIteratorConcept<const_reverse_iterator> >();
801
802      const_constraints(c);
803    }
804    void const_constraints(const RandomAccessContainer& cc) {
805      const_reference r = cc[n];
806      ignore_unused_variable_warning(r);
807    }
808    RandomAccessContainer c;
809    size_type n;
810  };
811
812  template <class RandomAccessContainer>
813  struct Mutable_RandomAccessContainerConcept
814  {
815    typedef typename RandomAccessContainer::size_type size_type;
816    typedef typename RandomAccessContainer::reference reference;
817    typedef typename RandomAccessContainer::iterator iterator;
818    typedef typename RandomAccessContainer::reverse_iterator reverse_iterator;
819
820    void constraints() {
821      function_requires<
822        RandomAccessContainerConcept<RandomAccessContainer> >();
823      function_requires<
824        Mutable_ReversibleContainerConcept<RandomAccessContainer> >();
825      function_requires< Mutable_RandomAccessIteratorConcept<iterator> >();
826      function_requires<
827        Mutable_RandomAccessIteratorConcept<reverse_iterator> >();
828
829      reference r = c[i];
830      ignore_unused_variable_warning(r);
831    }
832    size_type i;
833    RandomAccessContainer c;
834  };
835
836  // A Sequence is inherently mutable
837  template <class Sequence>
838  struct SequenceConcept
839  {
840
841    typedef typename Sequence::reference reference;
842    typedef typename Sequence::const_reference const_reference;
843
844    void constraints() {
845      // Matt Austern's book puts DefaultConstructible here, the C++
846      // standard places it in Container
847      //    function_requires< DefaultConstructible<Sequence> >();
848      function_requires< Mutable_ForwardContainerConcept<Sequence> >();
849      function_requires< DefaultConstructibleConcept<Sequence> >();
850
851      Sequence
852        c(n),
853        c2(n, t),
854        c3(first, last);
855
856      c.insert(p, t);
857      c.insert(p, n, t);
858      c.insert(p, first, last);
859
860      c.erase(p);
861      c.erase(p, q);
862
863      reference r = c.front();
864
865      ignore_unused_variable_warning(c);
866      ignore_unused_variable_warning(c2);
867      ignore_unused_variable_warning(c3);
868      ignore_unused_variable_warning(r);
869      const_constraints(c);
870    }
871    void const_constraints(const Sequence& c) {
872      const_reference r = c.front();
873      ignore_unused_variable_warning(r);
874    }
875    typename Sequence::value_type t;
876    typename Sequence::size_type n;
877    typename Sequence::value_type* first, *last;
878    typename Sequence::iterator p, q;
879  };
880
881  template <class FrontInsertionSequence>
882  struct FrontInsertionSequenceConcept
883  {
884    void constraints() {
885      function_requires< SequenceConcept<FrontInsertionSequence> >();
886
887      c.push_front(t);
888      c.pop_front();
889    }
890    FrontInsertionSequence c;
891    typename FrontInsertionSequence::value_type t;
892  };
893
894  template <class BackInsertionSequence>
895  struct BackInsertionSequenceConcept
896  {
897    typedef typename BackInsertionSequence::reference reference;
898    typedef typename BackInsertionSequence::const_reference const_reference;
899
900    void constraints() {
901      function_requires< SequenceConcept<BackInsertionSequence> >();
902
903      c.push_back(t);
904      c.pop_back();
905      reference r = c.back();
906      ignore_unused_variable_warning(r);
907    }
908    void const_constraints(const BackInsertionSequence& cc) {
909      const_reference r = cc.back();
910      ignore_unused_variable_warning(r);
911    };
912    BackInsertionSequence c;
913    typename BackInsertionSequence::value_type t;
914  };
915
916  template <class AssociativeContainer>
917  struct AssociativeContainerConcept
918  {
919    void constraints() {
920      function_requires< ForwardContainerConcept<AssociativeContainer> >();
921      function_requires< DefaultConstructibleConcept<AssociativeContainer> >();
922   
923      i = c.find(k);
924      r = c.equal_range(k);
925      c.erase(k);
926      c.erase(i);
927      c.erase(r.first, r.second);
928      const_constraints(c);
929    }
930    void const_constraints(const AssociativeContainer& cc) {
931      ci = cc.find(k);
932      n = cc.count(k);
933      cr = cc.equal_range(k);
934    }
935    typedef typename AssociativeContainer::iterator iterator;
936    typedef typename AssociativeContainer::const_iterator const_iterator;
937
938    AssociativeContainer c;
939    iterator i;
940    std::pair<iterator,iterator> r;
941    const_iterator ci;
942    std::pair<const_iterator,const_iterator> cr;
943    typename AssociativeContainer::key_type k;
944    typename AssociativeContainer::size_type n;
945  };
946
947  template <class UniqueAssociativeContainer>
948  struct UniqueAssociativeContainerConcept
949  {
950    void constraints() {
951      function_requires< AssociativeContainerConcept<UniqueAssociativeContainer> >();
952   
953      UniqueAssociativeContainer c(first, last);
954     
955      pos_flag = c.insert(t);
956      c.insert(first, last);
957
958      ignore_unused_variable_warning(c);
959    }
960    std::pair<typename UniqueAssociativeContainer::iterator, bool> pos_flag;
961    typename UniqueAssociativeContainer::value_type t;
962    typename UniqueAssociativeContainer::value_type* first, *last;
963  };
964
965  template <class MultipleAssociativeContainer>
966  struct MultipleAssociativeContainerConcept
967  {
968    void constraints() {
969      function_requires< AssociativeContainerConcept<MultipleAssociativeContainer> >();
970
971      MultipleAssociativeContainer c(first, last);
972     
973      pos = c.insert(t);
974      c.insert(first, last);
975
976      ignore_unused_variable_warning(c);
977      ignore_unused_variable_warning(pos);
978    }
979    typename MultipleAssociativeContainer::iterator pos;
980    typename MultipleAssociativeContainer::value_type t;
981    typename MultipleAssociativeContainer::value_type* first, *last;
982  };
983
984  template <class SimpleAssociativeContainer>
985  struct SimpleAssociativeContainerConcept
986  {
987    void constraints() {
988      function_requires< AssociativeContainerConcept<SimpleAssociativeContainer> >();
989      typedef typename SimpleAssociativeContainer::key_type key_type;
990      typedef typename SimpleAssociativeContainer::value_type value_type;
991      typedef typename require_same<key_type, value_type>::type req;
992    }
993  };
994
995  template <class SimpleAssociativeContainer>
996  struct PairAssociativeContainerConcept
997  {
998    void constraints() {
999      function_requires< AssociativeContainerConcept<SimpleAssociativeContainer> >();
1000      typedef typename SimpleAssociativeContainer::key_type key_type;
1001      typedef typename SimpleAssociativeContainer::value_type value_type;
1002      typedef typename SimpleAssociativeContainer::mapped_type mapped_type;
1003      typedef std::pair<const key_type, mapped_type> required_value_type;
1004      typedef typename require_same<value_type, required_value_type>::type req;
1005    }
1006  };
1007
1008  template <class SortedAssociativeContainer>
1009  struct SortedAssociativeContainerConcept
1010  {
1011    void constraints() {
1012      function_requires< AssociativeContainerConcept<SortedAssociativeContainer> >();
1013      function_requires< ReversibleContainerConcept<SortedAssociativeContainer> >();
1014
1015      SortedAssociativeContainer
1016        c(kc),
1017        c2(first, last),
1018        c3(first, last, kc);
1019
1020      p = c.upper_bound(k);
1021      p = c.lower_bound(k);
1022      r = c.equal_range(k);
1023     
1024      c.insert(p, t);
1025     
1026      ignore_unused_variable_warning(c);
1027      ignore_unused_variable_warning(c2);
1028      ignore_unused_variable_warning(c3);
1029    }
1030    void const_constraints(const SortedAssociativeContainer& c) {
1031      kc = c.key_comp();
1032      vc = c.value_comp();
1033
1034      cp = c.upper_bound(k);
1035      cp = c.lower_bound(k);
1036      cr = c.equal_range(k);
1037    }
1038    typename SortedAssociativeContainer::key_compare kc;
1039    typename SortedAssociativeContainer::value_compare vc;
1040    typename SortedAssociativeContainer::value_type t;
1041    typename SortedAssociativeContainer::key_type k;
1042    typedef typename SortedAssociativeContainer::iterator iterator;
1043    typedef typename SortedAssociativeContainer::const_iterator const_iterator;
1044    iterator p;
1045    const_iterator cp;
1046    std::pair<iterator,iterator> r;
1047    std::pair<const_iterator,const_iterator> cr;
1048    typename SortedAssociativeContainer::value_type* first, *last;
1049  };
1050
1051  // HashedAssociativeContainer
1052
1053} // namespace boost
1054
1055#endif // BOOST_CONCEPT_CHECKS_HPP
1056
Note: See TracBrowser for help on using the repository browser.