...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
To start using typeof include the typeof header:
#include <boost/typeof/typeof.hpp>
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<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 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 <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 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 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 parameters are 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 need to 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.