📄 typeof.qbk
字号:
[library Boost.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 <ulink url="http://www.boost.org/LICENSE_1_0.txt"> http://www.boost.org/LICENSE_1_0.txt </ulink>) ] [id typeof] [last-revision $Date: 2007-11-25 13:38:02 -0500 (Sun, 25 Nov 2007) $]][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 template parameters, as well as parameters to the constructor: std::pair<int, double>(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<int, double> p(5, 3.14159);The object generator no longer helps: std::pair<int, double> 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 complex types, and go a long way to hide this complexity behind object generators. Consider a nit Boost.Lambda functor: _1 > 15 && _2 < 20If 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<and_action>, tuple< lambda_functor< lambda_functor_base< relational_action<greater_action>, tuple< lambda_functor<placeholder<1> >, int const > > >, lambda_functor< lambda_functor_base< relational_action<less_action>, tuple< lambda_functor<placeholder<2> >, int const > > > > > > f = _1 > 15 && _2 < 20;Not exactly elegant. To solve this problem (as well as some other problems), the C++ standard committee is considering a few additions to the standard language, such as `typeof/decltype` and `auto` (see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1607.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1607.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;The purpose of the Boost.Typeof library is to provide a library-based solution, which could be used until the language-based facility is added to the Standardand becomes widely available. [endsect][section:tuto Tutorial]To start using typeof include the typeof header: #include <boost/typeof/typeof.hpp>To deduce the type of an expression at compile timeuse the `BOOST_TYPEOF` macro: namespace ex1 { typedef BOOST_TYPEOF(1 + 0.5) type; BOOST_STATIC_ASSERT((is_same<type, double>::value)); }In the dependent context use `BOOST_TYPEOF_TPL` instead of `BOOST_TYPEOF`: namespace ex2 { template<class T, class U> 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<type, double>::value)); }The above examples are possible because the Typeof Library knows about primitive types, such as `int`, `double`, `char`, etc. The Typeof Library alsoknows about most types and templates defined by the Standard C++ Library, but the appropriate headers need to be includedto take advantage of this: #include <boost/typeof/std/utility.hpp> namespace ex3 { BOOST_AUTO(p, make_pair(1, 2)); BOOST_STATIC_ASSERT((is_same<BOOST_TYPEOF(p), pair<int, int> >::value)); }Here `<boost/typeof/std/utility.hpp>` includes `<utility>` and contains knowledge about templates defined there. This naming convention applies in general, for example to let the Typeof Library handle `std::vector`,include `<boost/typeof/std/vector.hpp>`, 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 <boost/typeof/std/string.hpp> namespace ex4 { BOOST_AUTO(p, new int[20]); BOOST_STATIC_ASSERT((is_same<BOOST_TYPEOF(p), int*>::value)); }Both `BOOST_TYPEOF` and `BOOST_AUTO` strip top-level qualifiers. Therefore, to allocate for example a reference, it has to be specified 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 itunless you let it know about this type. You tell the Typeof Libraryabout a type (or template) by the means of "registering" this type/template.Any source or header file where types/templates are registered has to 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<type, pair<int, MyType> >::value)); }A template is registered by specifying its fully qualified name,and describing its parameters. In the simplest case, when all parametersare type parameters, only their number needs to be specified: namespace ex7 { template<class T, class U> struct MyTemplate {}; } BOOST_TYPEOF_REGISTER_TEMPLATE(ex7::MyTemplate, 2) namespace ex7 { typedef BOOST_TYPEOF(make_pair(1, MyTemplate<int, ex6::MyType>())) type; BOOST_STATIC_ASSERT((is_same<type, pair<int, MyTemplate<int, ex6::MyType> > >::value)); }When a template has integral template parameters, all parameters needto be described in the preprocessor sequence: namespace ex8 { template<class T, int n> struct MyTemplate {}; } BOOST_TYPEOF_REGISTER_TEMPLATE(ex8::MyTemplate, (class)(int)) namespace ex8 { typedef BOOST_TYPEOF(make_pair(1, MyTemplate<ex7::MyTemplate<ex6::MyType, int>, 0>())) type; BOOST_STATIC_ASSERT((is_same<type, pair<int, MyTemplate<ex7::MyTemplate<ex6::MyType, int>, 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][a variable to be initialized with the expression]] [[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 the `typename` keyword inside the `auto` expression.[h4 Sample Code] int 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 integraltemplate 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<color C0,typename T1> class class_with_enum {}; template<typename T0,T0 I1> 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 parametersare 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 sequenceused 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 supportedby 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: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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -