## Tutorial

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.