diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 0000000..9e4f293 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,28 @@ + +# Copyright Peder Holt 2005. Use, modification, and distribution are +# subject to the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +using quickbook ; + +xml typeof : typeof.qbk ; +boostbook standalone + : + typeof + : + nav.layout=none + navig.graphics=0 + ; + +install html : ../../../doc/html/boostbook.css ; +install ../ : ../../../boost.png ; + +if ! $(gWARNING_DONE) +{ + ECHO ; + ECHO This Jamfile is for testing the Typeof documentation build only ; + ECHO If you want to update your distributed documentation then please build ; + ECHO from the boost-path/doc directory ; + ECHO ; + gWARNING_DONE = "true" ; +} diff --git a/doc/typeof.qbk b/doc/typeof.qbk new file mode 100644 index 0000000..db4479a --- /dev/null +++ b/doc/typeof.qbk @@ -0,0 +1,874 @@ +[library Typeof + [authors [Vertleyb, Arkadiy], [Holt, Peder]] + [copyright 2004 2005 Arkadiy Vertleyb, Peder Holt] + [license + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + + http://www.boost.org/LICENSE_1_0.txt + ) + ] + [last-revision $Date$] +] + +[xinclude catalog.xml] + +[section:moti Motivation] + +[c++] + +Today many template libraries supply object generators to simplify object creation +by utilizing the C++ template argument deduction facility. Consider `std::pair`. +In order to instantiate this class template and create a temporary object of this instantiation, +one has to supply both type parameters and value parameters: + + std::pair(5, 3.14159); + +To avoid this duplication, STL supplies the `std::make_pair` object generator. +When it is used, the types of template parameters are deduced from supplied function arguments: + + std::make_pair(5, 3.14159); + +For the temporary objects it is enough. However, when a named object needs to be allocated, +the problem appears again: + + std::pair p(5, 3.14159); + +The object generator no longer helps: + + std::pair p = std::make_pair(5, 3.14159); + +It would be nice to deduce the type of the object (on the left) from the expression +it is initialized with (on the right), but the current C++ syntax does not allow for this. + +The above example demonstrates the essence of the problem but does not demonstrate its scale. +Many libraries, especially expression template libraries, create objects of really complicated types, +and go a long way to hide this complexity behind object generators. Consider a nit Boost.Lambda functor: + + _1 > 15 && _2 < 20 + +If one wanted to allocate a named copy of such an innocently looking functor, +she would have to specify something like this: + + lambda_functor< + lambda_functor_base< + logical_action, + tuple< + lambda_functor< + lambda_functor_base< + relational_action, + tuple< + lambda_functor >, + int const + > + > + >, + lambda_functor< + lambda_functor_base< + relational_action, + tuple< + lambda_functor >, + int const + > + > + > + > + > + > + f = _1 > 15 && _2 < 20; + + +Not exactly elegant. To solve this problem, the C++ standard committee is considering +a few additions to the standard language, such as `typeof/decltype` and `auto` (see +[@http://www.osl.iu.edu/~jajarvi/publications/papers/decltype_n1478.pdf +http://www.osl.iu.edu/~jajarvi/publications/papers/decltype_n1478.pdf]). + +The `typeof` operator (or `decltype`, which is a slightly different flavor of `typeof`) +allows one to determine the type of an expression at compile time. Using `typeof`, +the above example can be simplified drastically: + + typeof(_1 > 15 && _2 < 20) f = _1 > 15 && _2 < 20; + +Much better, but some duplication still exists. The `auto` type solves the rest of the problem: + + auto f = _1 > 15 && _2 < 20; + +[endsect] + +[section:tuto Tutorial] + +To deduce the type of an expression at compile time +use the `BOOST_TYPEOF` macro: + + namespace ex1 + { + typedef BOOST_TYPEOF(1 + 0.5) type; + + BOOST_STATIC_ASSERT((is_same::value)); + } + +In the dependent context use `BOOST_TYPEOF_TPL` instead of `BOOST_TYPEOF`: + + namespace ex2 + { + template + BOOST_TYPEOF_TPL(T() + U()) add(const T& t, const U& u) + { + return t + u; + }; + + typedef BOOST_TYPEOF(add('a', 1.5)) type; + + BOOST_STATIC_ASSERT((is_same::value)); + } + +The above examples are possible because the Typeof Library knows about +primitive types, such as `int`, `double`, `char`, etc. The Typeof Library also +knows about most types and templates defined by the +Standard C++ Library, but the appropriate headers need to be included +to take advantage of this: + + #include + + namespace ex3 + { + BOOST_AUTO(p, make_pair(1, 2)); + + BOOST_STATIC_ASSERT((is_same >::value)); + } + +Here `` includes `` and contains +knowledge about templates defined there. This naming convention +applies in general, for example to let the Typeof Library handle `std::vector`, +include ``, etc. + +To deduce the type of a variable from the expression, this variable +is initialized with, use the `BOOST_AUTO` macro (or `BOOST_AUTO_TPL` +in a dependent context: + + #include + + namespace ex4 + { + BOOST_AUTO(p, new int[20]); + + BOOST_STATIC_ASSERT((is_same::value)); + } + +Both `BOOST_TYPEOF` and `BOOST_AUTO` strip top-level qualifiers. +Therefore, to allocate a reference, this has to be defined explicitly: + + namespace ex5 + { + string& hello() + { + static string s = "hello"; + return s; + } + + BOOST_AUTO(&s, hello()); + } + +To better understand this syntax, note that this gets expanded into: + + BOOST_TYPEOF(hello()) &s = hello(); + +If your define your own type, the Typeof Library cannot handle it +unless you let it know about this type. You tell the Typeof Library +about a type (or template) by the means of "registering" this type/template. + +Any source or header file where types/templates are registered should +contain the following line before any registration is done: + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +After this a type can be registered: + + namespace ex6 + { + struct MyType + {}; + } + + BOOST_TYPEOF_REGISTER_TYPE(ex6::MyType) + +The registration must be done from the context of global namespace; +fully qualified type name has to be used. + +Any number of types can be registered in one file, each on a separate line. + +Once your type is registered, the Typeof Library can handle it in any context: + + namespace ex6 + { + typedef BOOST_TYPEOF(make_pair(1, MyType())) type; + + BOOST_STATIC_ASSERT((is_same >::value)); + } + +A template is registered by specifying its fully qualified name, +and describing its parameters. In the simplest case, when all parameters +are type parameters, only their number needs to be specified: + + namespace ex7 + { + template + struct MyTemplate + {}; + } + + BOOST_TYPEOF_REGISTER_TEMPLATE(ex7::MyTemplate, 2) + + namespace ex7 + { + typedef BOOST_TYPEOF(make_pair(1, MyTemplate())) type; + + BOOST_STATIC_ASSERT((is_same > + >::value)); + } + +When a template has integral template parameters, all parameters need +to be described in the preprocessor sequence: + + namespace ex8 + { + template + struct MyTemplate + {}; + } + + BOOST_TYPEOF_REGISTER_TEMPLATE(ex8::MyTemplate, (class)(int)) + + namespace ex8 + { + typedef BOOST_TYPEOF(make_pair(1, MyTemplate, 0>())) type; + + BOOST_STATIC_ASSERT((is_same, 0> > + >::value)); + } + +Please see the reference for more details. + +[endsect] + +[section:refe Reference] + +[section:auto AUTO, AUTO_TPL] + +The `BOOST_AUTO` macro emulates the proposed `auto` keyword in C++. + +[h4 Usage] + + BOOST_AUTO(var,expr) + BOOST_AUTO_TPL(var,expr) + +[variablelist Arguments +[[var][initialized with expr]] +[[expr][a valid c++ expression]] +] + +[h4 Remarks] + +If you want to use `auto` in a template-context, use `BOOST_AUTO_TPL(expr)`, +which takes care of `typename` inside the `auto` expression. + +[h4 Sample Code] + + void main() + { + length::meter a(5); + force::newton b(6); + BOOST_AUTO(c, a * b); + } + +[endsect] + +[section:compl COMPLIANT] + +The `BOOST_TYPEOF_COMPLIANT` macro can be used to force the emulation mode. +Define it if your compiler by default uses another mode, such as native `typeof` +or Microsoft-specific trick, but you want to use the emulation mode, +for example for portability reasons. + +[endsect] + +[section:incr INCREMENT_REGISTRATION_GROUP] + +The `BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP` macro ensures that type registrations +in different header files receive unique identifiers. + +[h4 Usage] + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +[h4 Remarks] + +specified once in every cpp/hpp file where any registration is performed, +before any registration. + +[h4 Sample Code] + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + + class X; + BOOST_TYPEOF_REGISTER_TYPE(X) + +[endsect] + +[section:inte INTEGRAL] + +The `BOOST_TYPEOF_INTEGRAL` macro is used when registering an integral +template parameter using `BOOST_TYPEOF_REGISTER_TEMPLATE`. + +Useful for `enum`s and dependent integral template parameters. + +[h4 Usage] + + BOOST_TYPEOF_INTEGRAL(x) + +[variablelist Arguments +[[x][a fully qualified integral type or enum]] +] + +[h4 Remarks] + +A short syntax has been implemented for the built in types +(int, bool, long, unsigned long, etc.) +Other non-type template parameters (e.g. pointer to member) +are not supported. + +[h4 Sample Code] + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + + namespace foo + { + enum color {red, green, blue}; + + template + class class_with_enum {}; + + template + class class_with_dependent_non_type {}; + } + + BOOST_TYPEOF_REGISTER_TEMPLATE(foo::class_with_enum, + (BOOST_TYPEOF_INTEGRAL(foo::color)) + (typename) + ) + + BOOST_TYPEOF_REGISTER_TEMPLATE(foo::class_with_dependent_non_type, + (typename) + (BOOST_TYPEOF_INTEGRAL(P0)) + ) + +[endsect] + +[section:limit_func LIMIT_FUNCTION_ARITY] + +The `BOOST_TYPEOF_LIMIT_FUNCTION_ARITY` macro defines how many parameters +are supported for functios, and applies to functions, function pointers, +function references, and member function pointers. The default value is 10. +Redefine if you want the Typeof Library to handle functions with more parameters. + +[endsect] + +[section:limit_size LIMIT_SIZE] + +The `BOOST_TYPEOF_LIMIT_SIZE` macro defines the size of the compile-time sequence +used to encode a type. The default value is 50. Increase it if you want +the Typeof Library to handle very complex types, although this +possibility is limited by the maximum number of template parameters supported +by your compiler. On the other hand, if you work only with very simple types, +decreasing this number may help to boost compile-time performance. + +[endsect] + +[section:lval LVALUE_TYPEOF] + +The `BOOST_LVALUE_TYPEOF` macro preserves the L-valueness of an expression. + +[h4 Usage] + + BOOST_LVALUE_TYPEOF(expr) + +[variablelist Arguments +[[expr][a valid c++ expression that has a type]] +] + +[h4 Remarks] + +This macro attempts to emulate the `decltype`. Its rules, however, +are directly built on the rules of binding a reference, and therefore +differ from the ones of real `decltype`: + +[table rules of LVALUE_TYPEOF +[[expr][decltype][LVALUE_TYPEOF]] +[[int i;][int][int&]] +[[const int ci = 0;][const int][const int&]] +[[int& ri = i;][int&][int&]] +[[const int& cri = ci;][const int&][const int&]] +[[int foo();][int][int]] +[[const int foo();][const int][const int&]] +[[int& foo();][int&][int&]] +[[const int& foo();][const int&][const int&]] +[[21][int][compiler-dependent]] +[[int(21)][int][int]] +] + +[h4 Sample Code] + + int& get_value(int& a); + int get_value(const double& a); + + void main() + { + int a=5; + typedef BOOST_LVALUE_TYPEOF(get_value(a)) type; + } + +[endsect] + +[section:regtype REGISTER_TYPE] + +The `BOOST_TYPEOF_REGISTER_TYPE` macro informs the Typeof Library +about the existence of a type + +[h4 Usage] + + BOOST_TYPEOF_REGISTER_TYPE(x) + +[variablelist Arguments +[[x][a fully qualified type]] +] + +[h4 Remarks] + +Must be used in the global namespace + +[h4 Sample Code] + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + + namespace foo + { + class bar {}; + enum color {red, green, blue}; + } + + BOOST_TYPEOF_REGISTER_TYPE(foo::bar) + BOOST_TYPEOF_REGISTER_TYPE(foo::color) + +[endsect] + +[section:regtemp REGISTER_TEMPLATE] + +The `BOOST_TYPEOF_REGISTER_TEMPLATE` macro informs the Typeof Library +about the existence of a template and describes its parameters + +[h4 Usage] + + BOOST_TYPEOF_REGISTER_TEMPLATE(x, n) + BOOST_TYPEOF_REGISTER_TEMPLATE(x, seq) + +[variablelist Arguments +[[x][a fully qualified template]] +[[n][the number of template arguments. Only valid if all template arguments are typenames]] +[[seq][a sequence of template arguments. Must be used when integral or template template parameters are present]] +] + +[h4 Remarks] + +Must be used in the global namespace. + +The library allows registration of templates with type, integral, +and template template parameters: + +* A type template parameter is described by the `(class)` or `(typename)` sequence element +* A template parameter of a well-known integral type can be described by +simply supplying its type, like `(unsigned int)`. +The following well-known integral types are supported: + * `[signed/unsigned] char` + * `[unsigned] short` + * `[unsigned] int` + * `[unsigned] long` + * `unsigned` + * `bool` + * `size_t` +* Enums and typedefs of integral types, need to be described explicitly +with the `BOOST_TYPEOF_INTEGRAL` macro, like `(BOOST_TYPEOF_INTEGRAL(MyEnum))` +* Template template parameters are described with the `BOOST_TYPEOF_TEMPLATE` macro, +like: `(BOOST_TYPEOF_TEMPLATE((class)(unsigned int)))`. +In case of all type parameters this can be shortened to something like `(BOOST_TYPEOF_TEMPLATE(2))`. +The nested template template parameters are not supported. + +[h4 Sample Code] + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + + namespace foo + { + template + class simple_template {}; + + template + class class_with_integral_constant {}; + } + + BOOST_TYPEOF_REGISTER_TEMPLATE(foo::simple_template, 2) + BOOST_TYPEOF_REGISTER_TEMPLATE(foo::class_with_integral_constant, (typename)(int)) + +[endsect] + +[section:temp TEMPLATE] + +The `BOOST_TYPEOF_TEMPLATE` macro is used when registering template template parameters +using `BOOST_TYPEOF_REGISTER_TEMPLATE`. + +[h4 Usage] + + BOOST_TYPEOF_TEMPLATE(n) + BOOST_TYPEOF_TEMPLATE(seq) + +[variablelist Arguments +[[n][the number of template arguments. Only valid if all template arguments are typenames]] +[[seq][a sequence of template arguments. Must be used when there are integral constants in the nested template]] +] + +[h4 Remarks] + +Can not be used to register nested template template parameters. + +[h4 Sample Code] + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + + namespace foo + { + enum color {red, green, blue}; + + template class T1> + class nested_template_class {}; + + template class T1> + class nested_with_integral {}; + } + + BOOST_TYPEOF_REGISTER_TEMPLATE(foo::nested_template_class, + (foo::color) + (BOOST_TYPEOF_TEMPLATE(1)) + ) + + BOOST_TYPEOF_REGISTER_TEMPLATE(foo::nested_with_integral, + (BOOST_TYPEOF_TEMPLATE((typename)(unsigned char))) + ) + +[endsect] + +[section:typo TYPEOF, TYPEOF_TPL] + +The `BOOST_TYPEOF` macro calculates the type of an expression, +but removes the top-level qualifiers, `const&` + +[h4 Usage] + + BOOST_TYPEOF(expr) + BOOST_TYPEOF_TPL(expr) + +[variablelist Arguments +[[expr][a valid c++ expression that has a type]] +] + +[h4 Remarks] + +If you want to use `typeof` in a template-context, use `BOOST_TYPEOF_TPL(expr)`, +which takes care of `typename` inside the `typeof` expression. + +[h4 Sample Code] + + template + struct result_of_conditional + { + typedef BOOST_TYPEOF_TPL(true?A():B()) type; + }; + + template + result_of_conditional::type min(const A& a,const B& b) + { + return a < b ? a : b; + } + +[endsect] + +[endsect] + +[section:other Other considerations and tips] + +[section:natem Native typeof support and emulation] + +Many compilers support typeof already, most noticeable GCC and Metrowerks. + +Igor Chesnokov recently discovered a method that allows to implement `typeof` +on the VC series of compilers. It uses a bug in the Microsoft compiler +that allows a nested class of base to be defined in a class derived from base: + + template struct typeof_access + { + struct id2type; //not defined + }; + + template struct typeof_register : typeof_access + { + // define base's nested class here + struct typeof_access::id2type + { + typedef T type; + }; + }; + + //Type registration function + typeof_register register_type(const T&); + + //Actually register type by instantiating typeof_register for the correct type + sizeof(register_type(some-type)); + + //Use the base class to access the type. + typedef typeof_access::id2type::type type; + +This method has also been adapted to VC7.0, where the nested class +is a template class that is specialized in the derived class. +The loopholes have been fixed in VC8.0 though, so on this compiler +this method doesn't work. + +For this and many other compilers neither native `typeof` support +nor the trick described above is an option. For such compilers +the emulation method is the only way of implementing `typeof`. + +According to a rough estimate, at the time of this writing +the introduction of the `typeof`, `auto`, etc., into the C++ standard +may not happen soon. Even after it's done, some time still has to pass +before most compilers implement this feature. But even after that, +there always are legacy compilers to support (for example now, in 2005, +many people are still using VC6, long after VC7.x, and even VC8.0 beta became available). + +Considering extreme usefulness of the feature right now, +it seems to make sense to implement it at the library level. + +The emulation mode seems to be important even if a better option is present +on some particular compiler. If a library author wants to develop portable +code using `typeof`, she needs to use emulation mode and register her types and +templates. Those users who have a better option can still take +advantage of it, since the registration macros are defined as no-op on +such compilers, while the users for whom emulation is the only option will use it. + +The other consideration applies to the users of VC7.1. Even though the more +convenient `typeof` trick is available, the possibility of upgrade to VC8, +where emulation remains the only option, should be considered. + +The emulation mode can be forced on the compilers that don't use it +by default by defining the `BOOST_TYPEOF_COMPLIANT` symbol: + + g++ -D BOOST_TYPEOF_COMPLIANT -I \boost\boost_1_32_0 main.cpp + +[endsect] + +[section:parties The three participating parties] + +The Lambda example from the Motivation section requires the following registration: + + #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::tuples::tuple, 2); + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor, 1); + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::lambda_functor_base, 2); + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::relational_action, 1); + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::logical_action, 1); + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::other_action, 1); + BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::greater_action); + BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::less_action); + BOOST_TYPEOF_REGISTER_TYPE(boost::lambda::and_action); + BOOST_TYPEOF_REGISTER_TEMPLATE(boost::lambda::placeholder, (int)); + +It may seem that the price for the ability to discover the expression's type +is too high: rather large amount of registration is required. +However note that all of the above registration is done only once, +and after that, any combination of the registered types and templates +would be handled. Moreover, this registration is typically done +not by the end-user, but rather by a layer on top of some library +(in this example -- Boost.Lambda). + +When thinking about this, it's helpful to consider three parties: the typeof facility, +the library (probably built on expression templates principle), and the end-user. +The typeof facility is responsible for registering fundamental types. +The library can register its own types and templates. + +In the best-case scenario, if the expressions always consist of only +fundamental types and library-defined types and templates, a library author +can achieve the impression that the `typeof` is natively supported for her library. +On the other hand, the more often expressions contain user-defined types, +the more responsibility is put on the end-user, and therefore the less attractive +this approach becomes. + +Thus, the ratio of user-defined types in the expressions should be the main +factor to consider when deciding whether or not to apply the typeof facility. + +[endsect] + +[section:features Supported features] + +The Typeof library pre-registers fundamental types. For these types, +and for any other types/templates registered by the user library or end-user, +any combination of the following is supported: + +* Pointers; +* References (except top-level); +* Consts (except top-level); +* Volatiles (except top-level); +* Arrays; +* Functions, function pointers, and references; +* Pointers to member functions; +* Pointers to data members. + +For example the following type: + + int& (*)(const volatile char*, double[5], void(*)(short)) + +is supported right away, and something like: + + void (MyClass::*)(int MyClass::*, MyClass[10]) const + +is supported provided `MyClass` is registered. + +The Typeof Library also provides registration files for most STL classes/templates. +These files are located in the std subdirectory, and named after corresponding STL headers. +These files are not included by the typeof system and have to be explicitly included +by the user, as needed: + + #include + BOOST_AUTO(fun, std::bind2nd(std::less(), 21)); //create named function object for future use. + +[endsect] + +[section:what What needs to be registered?] + +It is possible to take advantage of the compiler when registering types for the Typeof Library. +Even though there is currently no direct support for typeof in the language, +the compiler is aware of what the type of an expression is, and gives an error +if it encounters an expression that has not been handled correctly. In the `typeof` context, +this error message will contain clues to what types needs to be registered with the +Typeof Library in order for `BOOST_TYPEOF` to work. + + struct X {}; + + template + struct Y {}; + + std::pair > a; + + BOOST_AUTO(a,b); + +We get the following error message from VC7.1 + +[pre + error C2504: 'boost::type_of::'anonymous-namespace'::encode_type_impl' : base + class undefined + with + \[ + V=boost::type_of::'anonymous-namespace'::encode_type_impl,std::pair>>::V0, + Type_Not_Registered_With_Typeof_System=X + \] +] + +Inspecting this error message, we see that the compiler complains about `X` + + BOOST_TYPEOF_REGISTER_TYPE(X); //register X with the typeof system + +Recompiling, we get a new error message from VC7.1 + +[pre + error C2504: 'boost::type_of::'anonymous-namespace'::encode_type_impl' : base + class undefined + with + \[ + V=boost::type_of::'anonymous-namespace'::encode_type_impl,std::pair>>::V1, + Type_Not_Registered_With_Typeof_System=Y + \] +] + +Inspecting this error message, we see that the compiler complains about `Y`. +Since `Y` is a template, and contains integral constants, we need to take more care when registering: + + BOOST_TYPEOF_REGISTER_TEMPLATE(Y,(typename)(bool)); //register template class Y + +It is a good idea to look up the exact definition of `Y` when it contains integral constants. +For simple template classes containing only typenames, you can rely solely on the compiler error. + +The above code now compiles. + +This technique can be used to get an overview of which types needs to be registered +for a given project in order to support `typeof`. + +[endsect] + +[section:comp Compilers] + +The system has been tested with the following compilers: + +* MSVC 6.5/7.0/7.1/8.0; +* GCC 3.4.2 + +[endsect] + +[section:limi Limitations] + +Nested template template parameters are not supported, like: + + template class> class Tpl> + class A; // can't register! + +Classes and templates nested inside other templates also can't be registered +because of the issue of nondeduced context. This limitation is most noticeable +with regards to standard iterators in Dinkumware STL, which are implemented +as nested classes. Instead, instantiations can be registered: + + BOOST_TYPEOF_REGISTER_TYPE(std::list::const_iterator) + +[endsect] + +[endsect] + +[section:cont Contributed By:] + +* Compliant compilers -- Arkadiy Vertleyb, Peder Holt +* MSVC 6.5, 7.0, 7.1 -- Igor Chesnokov, Peder Holt + +[endsect] + +[section:ackn Acknoledgements] + +The idea of representing a type as multiple compile-time integers, +and passing these integers across function boundaries using sizeof(), +was taken from Steve Dewhurst's article "A Bitwise typeof Operator", CUJ 2002. +This article can also be viewed online, at [@http://www.semantics.org/localarchive.html +http://www.semantics.org/localarchive.html]. + +Special thank you to Paul Mensonides, Vesa Karvonen, and Aleksey Gurtovoy +for the Boost Preprocessor Library and MPL. Without these two libraries, +this typeof implementation would not exist. + +The following people provided support, gave valuable comments, +or in any other way contributed to the library development +(in alphabetical order): + +* David Abrahams +* Andrey Beliakov +* Joel de Guzman +* Daniel James +* Vesa Karvonen +* Paul Mensonides +* Alexander Nasonov +* Martin Wille + +[endsect]