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