]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/typeof/doc/typeof.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / typeof / doc / typeof.qbk
1 [library Boost.Typeof
2 [authors [Vertleyb, Arkadiy], [Holt, Peder]]
3 [copyright 2004 2005 Arkadiy Vertleyb, Peder Holt]
4 [license
5 Distributed under the Boost Software License, Version 1.0.
6 (See accompanying file LICENSE_1_0.txt or copy at
7 <ulink url="http://www.boost.org/LICENSE_1_0.txt">
8 http://www.boost.org/LICENSE_1_0.txt
9 </ulink>)
10 ]
11 [id typeof]
12 [last-revision $Date$]
13 ]
14
15 [section:moti Motivation]
16
17 [c++]
18
19 Today many template libraries supply object generators to simplify object creation
20 by utilizing the C++ template argument deduction facility. Consider `std::pair`.
21 In order to instantiate this class template and create a temporary object of this instantiation,
22 one has to supply template parameters, as well as parameters to the constructor:
23
24 std::pair<int, double>(5, 3.14159);
25
26 To avoid this duplication, STL supplies the `std::make_pair` object generator.
27 When it is used, the types of template parameters are deduced from supplied function arguments:
28
29 std::make_pair(5, 3.14159);
30
31 For the temporary objects it is enough. However, when a named object needs to be allocated,
32 the problem appears again:
33
34 std::pair<int, double> p(5, 3.14159);
35
36 The object generator no longer helps:
37
38 std::pair<int, double> p = std::make_pair(5, 3.14159);
39
40 It would be nice to deduce the type of the object (on the left) from the expression
41 it is initialized with (on the right), but the current C++ syntax does not allow for this.
42
43 The above example demonstrates the essence of the problem but does not demonstrate its scale.
44 Many libraries, especially expression template libraries, create objects of really complex types,
45 and go a long way to hide this complexity behind object generators. Consider a nit Boost.Lambda functor:
46
47 _1 > 15 && _2 < 20
48
49 If one wanted to allocate a named copy of such an innocently looking functor,
50 she would have to specify something like this:
51
52 lambda_functor<
53 lambda_functor_base<
54 logical_action<and_action>,
55 tuple<
56 lambda_functor<
57 lambda_functor_base<
58 relational_action<greater_action>,
59 tuple<
60 lambda_functor<placeholder<1> >,
61 int const
62 >
63 >
64 >,
65 lambda_functor<
66 lambda_functor_base<
67 relational_action<less_action>,
68 tuple<
69 lambda_functor<placeholder<2> >,
70 int const
71 >
72 >
73 >
74 >
75 >
76 >
77 f = _1 > 15 && _2 < 20;
78
79
80 Not exactly elegant. To solve this problem (as well as some other problems),
81 the C++ standard committee is considering
82 a few additions to the standard language, such as `typeof/decltype` and `auto` (see
83 [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1607.pdf
84 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1607.pdf]).
85
86 The `typeof` operator (or `decltype`, which is a slightly different flavor of `typeof`)
87 allows one to determine the type of an expression at compile time. Using `typeof`,
88 the above example can be simplified drastically:
89
90 typeof(_1 > 15 && _2 < 20) f = _1 > 15 && _2 < 20;
91
92 Much better, but some duplication still exists. The `auto` type solves the rest of the problem:
93
94 auto f = _1 > 15 && _2 < 20;
95
96 The purpose of the Boost.Typeof library is to provide a library-based solution,
97 which could be used until the language-based facility is added to the Standard
98 and becomes widely available.
99
100 [endsect]
101
102 [section:tuto Tutorial]
103
104 To start using typeof include the typeof header:
105
106 #include <boost/typeof/typeof.hpp>
107
108 To deduce the type of an expression at compile time
109 use the `BOOST_TYPEOF` macro:
110
111 namespace ex1
112 {
113 typedef BOOST_TYPEOF(1 + 0.5) type;
114
115 BOOST_STATIC_ASSERT((is_same<type, double>::value));
116 }
117
118 In the dependent context use `BOOST_TYPEOF_TPL` instead of `BOOST_TYPEOF`:
119
120 namespace ex2
121 {
122 template<class T, class U>
123 BOOST_TYPEOF_TPL(T() + U()) add(const T& t, const U& u)
124 {
125 return t + u;
126 };
127
128 typedef BOOST_TYPEOF(add('a', 1.5)) type;
129
130 BOOST_STATIC_ASSERT((is_same<type, double>::value));
131 }
132
133 The above examples are possible because the Typeof Library knows about
134 primitive types, such as `int`, `double`, `char`, etc. The Typeof Library also
135 knows about most types and templates defined by the
136 Standard C++ Library, but the appropriate headers need to be included
137 to take advantage of this:
138
139 #include <boost/typeof/std/utility.hpp>
140
141 namespace ex3
142 {
143 BOOST_AUTO(p, make_pair(1, 2));
144
145 BOOST_STATIC_ASSERT((is_same<BOOST_TYPEOF(p), pair<int, int> >::value));
146 }
147
148 Here `<boost/typeof/std/utility.hpp>` includes `<utility>` and contains
149 knowledge about templates defined there. This naming convention
150 applies in general, for example to let the Typeof Library handle `std::vector`,
151 include `<boost/typeof/std/vector.hpp>`, etc.
152
153 To deduce the type of a variable from the expression, this variable
154 is initialized with, use the `BOOST_AUTO` macro (or `BOOST_AUTO_TPL`
155 in a dependent context:
156
157 #include <boost/typeof/std/string.hpp>
158
159 namespace ex4
160 {
161 BOOST_AUTO(p, new int[20]);
162
163 BOOST_STATIC_ASSERT((is_same<BOOST_TYPEOF(p), int*>::value));
164 }
165
166 Both `BOOST_TYPEOF` and `BOOST_AUTO` strip top-level qualifiers.
167 Therefore, to allocate for example a reference, it has to be specified explicitly:
168
169 namespace ex5
170 {
171 string& hello()
172 {
173 static string s = "hello";
174 return s;
175 }
176
177 BOOST_AUTO(&s, hello());
178 }
179
180 To better understand this syntax, note that this gets expanded into:
181
182 BOOST_TYPEOF(hello()) &s = hello();
183
184 If your define your own type, the Typeof Library cannot handle it
185 unless you let it know about this type. You tell the Typeof Library
186 about a type (or template) by the means of "registering" this type/template.
187
188 Any source or header file where types/templates are registered has to
189 contain the following line before any registration is done:
190
191 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
192
193 After this a type can be registered:
194
195 namespace ex6
196 {
197 struct MyType
198 {};
199 }
200
201 BOOST_TYPEOF_REGISTER_TYPE(ex6::MyType)
202
203 The registration must be done from the context of global namespace;
204 fully qualified type name has to be used.
205
206 Any number of types can be registered in one file, each on a separate line.
207
208 Once your type is registered, the Typeof Library can handle it in any context:
209
210 namespace ex6
211 {
212 typedef BOOST_TYPEOF(make_pair(1, MyType())) type;
213
214 BOOST_STATIC_ASSERT((is_same<type, pair<int, MyType> >::value));
215 }
216
217 A template is registered by specifying its fully qualified name,
218 and describing its parameters. In the simplest case, when all parameters
219 are type parameters, only their number needs to be specified:
220
221 namespace ex7
222 {
223 template<class T, class U>
224 struct MyTemplate
225 {};
226 }
227
228 BOOST_TYPEOF_REGISTER_TEMPLATE(ex7::MyTemplate, 2)
229
230 namespace ex7
231 {
232 typedef BOOST_TYPEOF(make_pair(1, MyTemplate<int, ex6::MyType>())) type;
233
234 BOOST_STATIC_ASSERT((is_same<type,
235 pair<int, MyTemplate<int, ex6::MyType> >
236 >::value));
237 }
238
239 When a template has integral template parameters, all parameters need
240 to be described in the preprocessor sequence:
241
242 namespace ex8
243 {
244 template<class T, int n>
245 struct MyTemplate
246 {};
247 }
248
249 BOOST_TYPEOF_REGISTER_TEMPLATE(ex8::MyTemplate, (class)(int))
250
251 namespace ex8
252 {
253 typedef BOOST_TYPEOF(make_pair(1, MyTemplate<ex7::MyTemplate<ex6::MyType, int>, 0>())) type;
254
255 BOOST_STATIC_ASSERT((is_same<type,
256 pair<int, MyTemplate<ex7::MyTemplate<ex6::MyType, int>, 0> >
257 >::value));
258 }
259
260 Please see the reference for more details.
261
262 [endsect]
263
264 [section:refe Reference]
265
266 [section:auto AUTO, AUTO_TPL]
267
268 The `BOOST_AUTO` macro emulates the proposed `auto` keyword in C++.
269
270 [h4 Usage]
271
272 BOOST_AUTO(var,expr)
273 BOOST_AUTO_TPL(var,expr)
274
275 [variablelist Arguments
276 [[var][a variable to be initialized with the expression]]
277 [[expr][a valid c++ expression]]
278 ]
279
280 [h4 Remarks]
281
282 If you want to use `auto` in a template-context, use `BOOST_AUTO_TPL(expr)`,
283 which takes care of the `typename` keyword inside the `auto` expression.
284
285 [h4 Sample Code]
286
287 int main()
288 {
289 length::meter a(5);
290 force::newton b(6);
291 BOOST_AUTO(c, a * b);
292 }
293
294 [endsect]
295
296 [section:compl COMPLIANT]
297
298 The `BOOST_TYPEOF_COMPLIANT` macro can be used to force the emulation mode.
299 Define it if your compiler by default uses another mode, such as native `typeof`
300 or Microsoft-specific trick, but you want to use the emulation mode,
301 for example for portability reasons.
302
303 [endsect]
304
305 [section:incr INCREMENT_REGISTRATION_GROUP]
306
307 The `BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP` macro ensures that type registrations
308 in different header files receive unique identifiers.
309
310 [h4 Usage]
311
312 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
313
314 [h4 Remarks]
315
316 specified once in every cpp/hpp file where any registration is performed,
317 before any registration.
318
319 [h4 Sample Code]
320
321 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
322
323 class X;
324 BOOST_TYPEOF_REGISTER_TYPE(X)
325
326 [endsect]
327
328 [section:inte INTEGRAL]
329
330 The `BOOST_TYPEOF_INTEGRAL` macro is used when registering an integral
331 template parameter using `BOOST_TYPEOF_REGISTER_TEMPLATE`.
332
333 Useful for `enum`s and dependent integral template parameters.
334
335 [h4 Usage]
336
337 BOOST_TYPEOF_INTEGRAL(x)
338
339 [variablelist Arguments
340 [[x][a fully qualified integral type or enum]]
341 ]
342
343 [h4 Remarks]
344
345 A short syntax has been implemented for the built in types
346 (int, bool, long, unsigned long, etc.)
347 Other non-type template parameters (e.g. pointer to member)
348 are not supported.
349
350 [h4 Sample Code]
351
352 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
353
354 namespace foo
355 {
356 enum color {red, green, blue};
357
358 template<color C0,typename T1>
359 class class_with_enum {};
360
361 template<typename T0,T0 I1>
362 class class_with_dependent_non_type {};
363 }
364
365 BOOST_TYPEOF_REGISTER_TEMPLATE(foo::class_with_enum,
366 (BOOST_TYPEOF_INTEGRAL(foo::color))
367 (typename)
368 )
369
370 BOOST_TYPEOF_REGISTER_TEMPLATE(foo::class_with_dependent_non_type,
371 (typename)
372 (BOOST_TYPEOF_INTEGRAL(P0))
373 )
374
375 [endsect]
376
377 [section:limit_func LIMIT_FUNCTION_ARITY]
378
379 The `BOOST_TYPEOF_LIMIT_FUNCTION_ARITY` macro defines how many parameters
380 are supported for functios, and applies to functions, function pointers,
381 function references, and member function pointers. The default value is 10.
382 Redefine if you want the Typeof Library to handle functions with more parameters.
383
384 [endsect]
385
386 [section:messages MESSAGES]
387
388 Define `BOOST_TYPEOF_MESSAGE` before including boost/typeof/typeof.hpp to
389 include messages "using typeof emulation" and "using native typeof".
390 By default, these messages will not be displayed.
391
392 [endsect]
393
394 [section:limit_size LIMIT_SIZE]
395
396 The `BOOST_TYPEOF_LIMIT_SIZE` macro defines the size of the compile-time sequence
397 used to encode a type. The default value is 50. Increase it if you want
398 the Typeof Library to handle very complex types, although this
399 possibility is limited by the maximum number of template parameters supported
400 by your compiler. On the other hand, if you work only with very simple types,
401 decreasing this number may help to boost compile-time performance.
402
403 [endsect]
404
405 [section:regtype REGISTER_TYPE]
406
407 The `BOOST_TYPEOF_REGISTER_TYPE` macro informs the Typeof Library
408 about the existence of a type
409
410 [h4 Usage]
411
412 BOOST_TYPEOF_REGISTER_TYPE(x)
413
414 [variablelist Arguments
415 [[x][a fully qualified type]]
416 ]
417
418 [h4 Remarks]
419
420 Must be used in the global namespace
421
422 [h4 Sample Code]
423
424 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
425
426 namespace foo
427 {
428 class bar {};
429 enum color {red, green, blue};
430 }
431
432 BOOST_TYPEOF_REGISTER_TYPE(foo::bar)
433 BOOST_TYPEOF_REGISTER_TYPE(foo::color)
434
435 [endsect]
436
437 [section:regtemp REGISTER_TEMPLATE]
438
439 The `BOOST_TYPEOF_REGISTER_TEMPLATE` macro informs the Typeof Library
440 about the existence of a template and describes its parameters
441
442 [h4 Usage]
443
444 BOOST_TYPEOF_REGISTER_TEMPLATE(x, n)
445 BOOST_TYPEOF_REGISTER_TEMPLATE(x, seq)
446
447 [variablelist Arguments
448 [[x][a fully qualified template]]
449 [[n][the number of template arguments. Only valid if all template arguments are typenames]]
450 [[seq][a sequence of template arguments. Must be used when integral or template template parameters are present]]
451 ]
452
453 [h4 Remarks]
454
455 Must be used in the global namespace.
456
457 The library allows registration of templates with type, integral,
458 and template template parameters:
459
460 * A type template parameter is described by the `(class)` or `(typename)` sequence element
461 * A template parameter of a well-known integral type can be described by
462 simply supplying its type, like `(unsigned int)`.
463 The following well-known integral types are supported:
464 * `[signed/unsigned] char`
465 * `[unsigned] short`
466 * `[unsigned] int`
467 * `[unsigned] long`
468 * `unsigned`
469 * `bool`
470 * `size_t`
471 * Enums and typedefs of integral types, need to be described explicitly
472 with the `BOOST_TYPEOF_INTEGRAL` macro, like `(BOOST_TYPEOF_INTEGRAL(MyEnum))`
473 * Template template parameters are described with the `BOOST_TYPEOF_TEMPLATE` macro,
474 like: `(BOOST_TYPEOF_TEMPLATE((class)(unsigned int)))`.
475 In case of all type parameters this can be shortened to something like `(BOOST_TYPEOF_TEMPLATE(2))`.
476 The nested template template parameters are not supported.
477
478 [h4 Sample Code]
479
480 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
481
482 namespace foo
483 {
484 template<typename T0, typename T1>
485 class simple_template {};
486
487 template<typename T0, int I1>
488 class class_with_integral_constant {};
489 }
490
491 BOOST_TYPEOF_REGISTER_TEMPLATE(foo::simple_template, 2)
492 BOOST_TYPEOF_REGISTER_TEMPLATE(foo::class_with_integral_constant, (typename)(int))
493
494 [endsect]
495
496 [section:temp TEMPLATE]
497
498 The `BOOST_TYPEOF_TEMPLATE` macro is used when registering template template parameters
499 using `BOOST_TYPEOF_REGISTER_TEMPLATE`.
500
501 [h4 Usage]
502
503 BOOST_TYPEOF_TEMPLATE(n)
504 BOOST_TYPEOF_TEMPLATE(seq)
505
506 [variablelist Arguments
507 [[n][the number of template arguments. Only valid if all template arguments are typenames]]
508 [[seq][a sequence of template arguments. Must be used when there are integral constants in the nested template]]
509 ]
510
511 [h4 Remarks]
512
513 Can not be used to register nested template template parameters.
514
515 [h4 Sample Code]
516
517 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
518
519 namespace foo
520 {
521 enum color {red, green, blue};
522
523 template<color C0, template<typename> class T1>
524 class nested_template_class {};
525
526 template<template<typename, unsigned char> class T1>
527 class nested_with_integral {};
528 }
529
530 BOOST_TYPEOF_REGISTER_TEMPLATE(foo::nested_template_class,
531 (foo::color)
532 (BOOST_TYPEOF_TEMPLATE(1))
533 )
534
535 BOOST_TYPEOF_REGISTER_TEMPLATE(foo::nested_with_integral,
536 (BOOST_TYPEOF_TEMPLATE((typename)(unsigned char)))
537 )
538
539 [endsect]
540
541 [section:typo TYPEOF, TYPEOF_TPL]
542
543 The `BOOST_TYPEOF` macro calculates the type of an expression,
544 but removes the top-level qualifiers, `const&`
545
546 [h4 Usage]
547
548 BOOST_TYPEOF(expr)
549 BOOST_TYPEOF_TPL(expr)
550
551 [variablelist Arguments
552 [[expr][a valid c++ expression that can be bound to const T&]]
553 ]
554
555 [h4 Remarks]
556
557 If you want to use `typeof` in a template-context, use `BOOST_TYPEOF_TPL(expr)`,
558 which takes care of `typename` inside the `typeof` expression.
559
560 [h4 Sample Code]
561
562 template<typename A, typename B>
563 struct result_of_conditional
564 {
565 typedef BOOST_TYPEOF_TPL(true?A():B()) type;
566 };
567
568 template<typename A, typename B>
569 result_of_conditional<A, B>::type min(const A& a,const B& b)
570 {
571 return a < b ? a : b;
572 }
573
574 [endsect]
575
576 [section:typn TYPEOF_NESTED_TYPEDEF, TYPEOF_NESTED_TYPEDEF_TPL]
577
578 The `TYPEOF_NESTED_TYPEDEF` macro works in much the same way as the 'TYPEOF' macro does, but
579 workarounds several compiler deficiencies.
580
581 [h4 Usage]
582
583 BOOST_TYPEOF_NESTED_TYPEDEF(name,expr)
584 BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr)
585
586 [variablelist Arguments
587 [[name][a valid identifier to nest the typeof operation inside]
588 [expr][a valid c++ expression that can be bound to const T&]]
589 ]
590
591 [h4 Remarks]
592
593 'typeof_nested_typedef' nests the 'typeof' operation inside a struct. By doing this, the 'typeof' operation
594 can be split into two steps, deconfusing several compilers (notably VC7.1 and VC8.0) on the way.
595 This also removes the limitation imposed by `BOOST_TYPEOF_LIMIT_SIZE` and allows you to use 'typeof' on much
596 larger expressions.
597
598 If you want to use `typeof_nested_typedef` in a template-context, use `BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr)`,
599 which takes care of `typename` inside the `typeof` expression.
600
601 'typeof_nested_typedef' can not be used at function/block scope.
602
603 [h4 Sample Code]
604
605 template<typename A, typename B>
606 struct result_of_conditional
607 {
608 BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested,true?A():B())
609 typedef typename nested::type type;
610 };
611
612 template<typename A, typename B>
613 result_of_conditional<A, B>::type min(const A& a,const B& b)
614 {
615 return a < b ? a : b;
616 }
617
618 [endsect]
619
620 [endsect]
621
622 [section:other Other considerations and tips]
623
624 [section:natem Native typeof support and emulation]
625
626 Many compilers support typeof already, most noticeable GCC and Metrowerks.
627
628 Igor Chesnokov discovered a method that allows to implement `typeof`
629 on the VC series of compilers. It uses a bug in the Microsoft compiler
630 that allows a nested class of base to be defined in a class derived from base:
631
632 template<int ID> struct typeof_access
633 {
634 struct id2type; //not defined
635 };
636
637 template<class T, int ID> struct typeof_register : typeof_access
638 {
639 // define base's nested class here
640 struct typeof_access::id2type
641 {
642 typedef T type;
643 };
644 };
645
646 //Type registration function
647 typeof_register<T, compile-time-constant> register_type(const T&);
648
649 //Actually register type by instantiating typeof_register for the correct type
650 sizeof(register_type(some-type));
651
652 //Use the base class to access the type.
653 typedef typeof_access::id2type::type type;
654
655 Peder Holt adapted this method to VC7.0, where the nested class
656 is a template class that is specialized in the derived class.
657
658 In VC8.0, it seemed that all the bug-featire had been fixed, but
659 Steven Watanabe managed to implement a more rigorous version of the VC7.0 fix that
660 enables 'typeof' to be supported 'natively' here as well.
661
662 For many other compilers neither native `typeof` support
663 nor the trick described above is an option. For such compilers
664 the emulation method is the only way of implementing `typeof`.
665
666 According to a rough estimate, at the time of this writing
667 the introduction of the `typeof`, `auto`, etc., into the C++ standard
668 may not happen soon. Even after it's done, some time still has to pass
669 before most compilers implement this feature. But even after that,
670 there always are legacy compilers to support (for example now, in 2005,
671 many people are still using VC6, long after VC7.x, and even VC8.0 beta became available).
672
673 Considering extreme usefulness of the feature right now,
674 it seems to make sense to implement it at the library level.
675
676 The emulation mode seems to be important even if a better option is present
677 on some particular compiler. If a library author wants to develop portable
678 code using `typeof`, she needs to use emulation mode and register her types and
679 templates. Those users who have a better option can still take
680 advantage of it, since the registration macros are defined as no-op on
681 such compilers, while the users for whom emulation is the only option will use it.
682
683 The other consideration applies to the users of VC7.1. Even though the more
684 convenient `typeof` trick is available, the possibility of upgrade to VC8,
685 where emulation remains the only option, should be considered.
686
687 The emulation mode can be forced on the compilers that don't use it
688 by default by defining the `BOOST_TYPEOF_COMPLIANT` symbol:
689
690 g++ -D BOOST_TYPEOF_COMPLIANT -I \boost\boost_1_32_0 main.cpp
691
692 [endsect]
693
694 [section:parties The three participating parties]
695
696 The Lambda example from the Motivation section requires the following registration:
697
698 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
699
700 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::tuples::tuple, 2);
701 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor, 1);
702 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor_base, 2);
703 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::relational_action, 1);
704 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::logical_action, 1);
705 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::other_action, 1);
706 BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::greater_action);
707 BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::less_action);
708 BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::and_action);
709 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::placeholder, (int));
710
711 It may seem that the price for the ability to discover the expression's type
712 is too high: rather large amount of registration is required.
713 However note that all of the above registration is done only once,
714 and after that, any combination of the registered types and templates
715 would be handled. Moreover, this registration is typically done
716 not by the end-user, but rather by a layer on top of some library
717 (in this example -- Boost.Lambda).
718
719 When thinking about this, it's helpful to consider three parties: the typeof facility,
720 the library (probably built on expression templates principle), and the end-user.
721 The typeof facility is responsible for registering fundamental types.
722 The library can register its own types and templates.
723
724 In the best-case scenario, if the expressions always consist of only
725 fundamental types and library-defined types and templates, a library author
726 can achieve the impression that the `typeof` is natively supported for her library.
727 On the other hand, the more often expressions contain user-defined types,
728 the more responsibility is put on the end-user, and therefore the less attractive
729 this approach becomes.
730
731 Thus, the ratio of user-defined types in the expressions should be the main
732 factor to consider when deciding whether or not to apply the typeof facility.
733
734 [endsect]
735
736 [section:features Supported features]
737
738 The Typeof library pre-registers fundamental types. For these types,
739 and for any other types/templates registered by the user library or end-user,
740 any combination of the following is supported:
741
742 * Pointers;
743 * References (except top-level);
744 * Consts (except top-level);
745 * Volatiles (except top-level);
746 * Arrays;
747 * Functions, function pointers, and references;
748 * Pointers to member functions;
749 * Pointers to data members.
750
751 For example the following type:
752
753 int& (*)(const volatile char*, double[5], void(*)(short))
754
755 is supported right away, and something like:
756
757 void (MyClass::*)(int MyClass::*, MyClass[10]) const
758
759 is supported provided `MyClass` is registered.
760
761 The Typeof Library also provides registration files for most STL classes/templates.
762 These files are located in the std subdirectory, and named after corresponding STL headers.
763 These files are not included by the typeof system and have to be explicitly included
764 by the user, as needed:
765
766 #include <boost/typeof/std/functional.hpp>
767 BOOST_AUTO(fun, std::bind2nd(std::less<int>(), 21)); //create named function object for future use.
768
769 [endsect]
770
771 [section:what What needs to be registered?]
772
773 It is possible to take advantage of the compiler when registering types for the Typeof Library.
774 Even though there is currently no direct support for typeof in the language,
775 the compiler is aware of what the type of an expression is, and gives an error
776 if it encounters an expression that has not been handled correctly. In the `typeof` context,
777 this error message will contain clues to what types needs to be registered with the
778 Typeof Library in order for `BOOST_TYPEOF` to work.
779
780 struct X {};
781
782 template<typename A,bool B>
783 struct Y {};
784
785 std::pair<X,Y<int,true> > a;
786
787 BOOST_AUTO(a,b);
788
789 We get the following error message from VC7.1
790
791 [pre
792 error C2504: 'boost::type_of::'anonymous-namespace'::encode_type_impl<V,Type_Not_Registered_With_Typeof_System>' : base
793 class undefined
794 with
795 \[
796 V=boost::type_of::'anonymous-namespace'::encode_type_impl<boost::mpl::vector0<boost::mpl::na>,std::pair<X,Y<int,true>>>::V0,
797 Type_Not_Registered_With_Typeof_System=X
798 \]
799 ]
800
801 Inspecting this error message, we see that the compiler complains about `X`
802
803 BOOST_TYPEOF_REGISTER_TYPE(X); //register X with the typeof system
804
805 Recompiling, we get a new error message from VC7.1
806
807 [pre
808 error C2504: 'boost::type_of::'anonymous-namespace'::encode_type_impl<V,Type_Not_Registered_With_Typeof_System>' : base
809 class undefined
810 with
811 \[
812 V=boost::type_of::'anonymous-namespace'::encode_type_impl<boost::mpl::vector0<boost::mpl::na>,std::pair<X,Y<int,true>>>::V1,
813 Type_Not_Registered_With_Typeof_System=Y<int,true>
814 \]
815 ]
816
817 Inspecting this error message, we see that the compiler complains about `Y<int,true>`.
818 Since `Y` is a template, and contains integral constants, we need to take more care when registering:
819
820 BOOST_TYPEOF_REGISTER_TEMPLATE(Y,(typename)(bool)); //register template class Y
821
822 It is a good idea to look up the exact definition of `Y` when it contains integral constants.
823 For simple template classes containing only typenames, you can rely solely on the compiler error.
824
825 The above code now compiles.
826
827 This technique can be used to get an overview of which types needs to be registered
828 for a given project in order to support `typeof`.
829
830 [endsect]
831
832 [section:limi Limitations]
833
834 Nested template template parameters are not supported, like:
835
836 template<template<template<class> class> class Tpl>
837 class A; // can't register!
838
839 Classes and templates nested inside other templates also can't be registered
840 because of the issue of nondeduced context. This limitation is most noticeable
841 with regards to standard iterators in Dinkumware STL, which are implemented
842 as nested classes. Instead, instantiations can be registered:
843
844 BOOST_TYPEOF_REGISTER_TYPE(std::list<int>::const_iterator)
845
846 [endsect]
847
848 [endsect]
849
850 [section:cont Contributed By:]
851
852 * Compliant compilers -- Arkadiy Vertleyb, Peder Holt
853 * MSVC 6.5, 7.0, 7.1 -- Igor Chesnokov, Peder Holt
854
855 [endsect]
856
857 [section:ackn Acknowledgements]
858
859 The idea of representing a type as multiple compile-time integers,
860 and passing these integers across function boundaries using sizeof(),
861 was taken from Steve Dewhurst's article "A Bitwise typeof Operator", CUJ 2002.
862 This article can also be viewed online, at [@http://www.semantics.org/localarchive.html
863 http://www.semantics.org/localarchive.html].
864
865 Special thank you to Paul Mensonides, Vesa Karvonen, and Aleksey Gurtovoy
866 for the Boost Preprocessor Library and MPL. Without these two libraries,
867 this typeof implementation would not exist.
868
869 The following people provided support, gave valuable comments,
870 or in any other way contributed to the library development
871 (in alphabetical order):
872
873 * David Abrahams
874 * Andrey Beliakov
875 * Joel de Guzman
876 * Daniel James
877 * Vesa Karvonen
878 * Andy Little
879 * Paul Mensonides
880 * Alexander Nasonov
881 * Tobias Schwinger
882 * Martin Wille
883
884 [endsect]