~ubuntu-branches/ubuntu/breezy/aqsis/breezy

« back to all changes in this revision

Viewing changes to boost/boost/concept_check.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Will Newton
  • Date: 2004-12-07 20:06:49 UTC
  • Revision ID: james.westby@ubuntu.com-20041207200649-fccswkrvp4oc8lmn
Tags: upstream-0.9.3
ImportĀ upstreamĀ versionĀ 0.9.3

Show diffs side-by-side

added added

removed removed

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