Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

Examples

Getting human readable and mangled type names
Storing information about a type in container
Getting through the inheritance to receive a real type name
Exact type matching: storing type with const, volatile and reference qualifiers
Table of raw_name() and pretty_name() outputs with and without RTTI

The following example shows how short (mangled) and human readable type names could be obtained from a type. Works with and without RTTI.

#include <boost/type_index.hpp>
#include <iostream>

template <class T>
void foo(T) {
    std::cout << "\n Short name: " << boost::typeindex::type_id<T>().raw_name();
    std::cout << "\n Readable name: " << boost::typeindex::type_id<T>().pretty_name();
}

struct user_defined_type{};

namespace ns1 { namespace ns2 {
    struct user_defined_type{};
}} // namespace ns1::ns2

namespace {
    struct in_anon_type{};
} // anonymous namespace

int main() {
    // Call to
    foo(1);
    // will output something like this:
    //
    // (RTTI on)                                            (RTTI off)
    // Short name: i                                        Short name: int]
    // Readable name: int                                   Readable name: int

    user_defined_type t;
    foo(t);
    // Will output:
    //
    // (RTTI on)                                            (RTTI off)
    // Short name: 17user_defined_type                      user_defined_type]
    // Readable name: user_defined_type                     user_defined_type

    ns1::ns2::user_defined_type t_in_ns;
    foo(t_in_ns);
    // Will output:
    //
    // (RTTI on)                                            (RTTI off)
    // Short name: N3ns13ns217user_defined_typeE            ns1::ns2::user_defined_type]
    // Readable name: ns1::ns2::user_defined_type           ns1::ns2::user_defined_type

    in_anon_type anon_t;
    foo(anon_t);
    // Will output:
    //
    // (RTTI on)                                            (RTTI off)
    // Short name: N12_GLOBAL__N_112in_anon_typeE           {anonymous}::in_anon_type]
    // Readable name: (anonymous namespace)::in_anon_type   {anonymous}::in_anon_type
}

Short names are very compiler dependant: some compiler will output .H, others i.

Readable names may also differ between compilers: struct user_defined_type, user_defined_type.

[Warning] Warning

With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'.

The following example shows how an information about a type could be stored. Example works with and without RTTI.

#include <boost/type_index.hpp>
#include <boost/unordered_set.hpp>
#include <boost/functional/hash.hpp>
#include <cassert>

int main() {
    boost::unordered_set<boost::typeindex::type_index> types;

    // Storing some `boost::type_info`s
    types.insert(boost::typeindex::type_id<int>());
    types.insert(boost::typeindex::type_id<float>());

    // `types` variable contains two `boost::type_index`es:
    assert(types.size() == 2);

    // Const, volatile and reference will be striped from the type:
    bool is_inserted = types.insert(boost::typeindex::type_id<const int>()).second;
    assert(!is_inserted);
    assert(types.erase(boost::typeindex::type_id<float&>()) == 1);

    // We have erased the `float` type, only `int` remains
    assert(*types.begin() == boost::typeindex::type_id<int>());
}

The following example shows that type_info is able to store the real type, successfully getting through all the inheritances.

Example works with and without RTTI."

#include <boost/type_index.hpp>
#include <iostream>

struct A {
    BOOST_TYPE_INDEX_REGISTER_CLASS
    virtual ~A(){}
};
struct B: public A { BOOST_TYPE_INDEX_REGISTER_CLASS };
struct C: public B { BOOST_TYPE_INDEX_REGISTER_CLASS };

void print_real_type(const A& a) {
    std::cout << boost::typeindex::type_id_runtime(a).pretty_name() << '\n';
}

int main() {
    C c;
    const A& c_as_a = c;
    print_real_type(c_as_a);    // Outputs `struct C`
    print_real_type(B());       // Outputs `struct B`
}

The following example shows that type_index (and type_info) is able to store the exact type, without stripping const, volatile and references. Example works with and without RTTI.

In this example we'll create a class that stores a pointer to function and remembers the exact type of the parameter the function accepts. When the call to the bound function is made, he actual input parameter type is checked against the stored parameter type and an exception is thrown in case of mismatch.

#include <boost/type_index.hpp>
#include <iostream>
#include <stdexcept>
#include <cassert>

class type_erased_unary_function {
    void*                           function_ptr_;
    boost::typeindex::type_index    exact_param_t_;

public:
    template <class ParamT>
    type_erased_unary_function(void(*ptr)(ParamT))
        : function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT`
        , exact_param_t_(boost::typeindex::type_id_with_cvr<ParamT>())
    {}

    template <class ParamT>
    void call(ParamT v) {
        if (exact_param_t_ != boost::typeindex::type_id_with_cvr<ParamT>()) {
            throw std::runtime_error("Incorrect `ParamT`");
        }

        return (reinterpret_cast<void(*)(ParamT)>(function_ptr_))(v);
    }
};

void foo(int){}

int main() {
    type_erased_unary_function func(&foo);
    func.call(100); // OK, `100` has type `int`

    try {
        int i = 100;

        // An attempt to convert stored function to a function accepting reference
        func.call<int&>(i); // Will throw, because types `int&` and `int` mismatch

        assert(false);
    } catch (const std::runtime_error& /*e*/) {}
}

The following example shows how different type names look when we explicitly use classes for RTTI and RTT off.

This example requires RTTI. For a more portable example see 'Getting human readable and mangled type names':

#include <boost/type_index/stl_type_index.hpp>
#include <boost/type_index/ctti_type_index.hpp>
#include <iostream>

template <class T>
void print(const char* name) {
    boost::typeindex::stl_type_index sti = boost::typeindex::stl_type_index::type_id<T>();
    boost::typeindex::ctti_type_index cti = boost::typeindex::ctti_type_index::type_id<T>();
    std::cout << "\t[" /* start of the row */
        << "[" << name << "]"
        << "[`" << sti.raw_name() << "`] "
        << "[`" << sti.pretty_name() << "`] "
        << "[`" << cti.raw_name() << "`] "
    << "]\n" /* end of the row */ ;
}

struct user_defined_type{};

namespace ns1 { namespace ns2 {
    struct user_defined_type{};
}} // namespace ns1::ns2

namespace {
    struct in_anon_type{};
} // anonymous namespace

namespace ns3 { namespace { namespace ns4 {
    struct in_anon_type{};
}}} // namespace ns3::{anonymous}::ns4


template <class T0, class T1>
class templ {};

template <>
class templ<int, int> {};

int main() {
    std::cout << "[table:id Table of names\n";
    std::cout << "\t[[Type] [RTTI & raw_name] [RTTI & pretty_name] [noRTTI & raw_name]]\n";

    print<user_defined_type>("User defined type");
    print<in_anon_type>("In anonymous namespace");
    print<ns3::ns4::in_anon_type>("In ns3::{anonymous}::ns4 namespace");
    print<templ<short, int> >("Template class");
    print<templ<int, int> >("Template class (full specialization)");
    print<templ<
        templ<char, signed char>,
        templ<int, user_defined_type>
    > >("Template class with templae classes");


    std::cout << "]\n";
}

Code from the example will produce the following table:

Table 34.2. Table of names

Type

RTTI & raw_name

RTTI & pretty_name

noRTTI & raw_name

User defined type

17user_defined_type

user_defined_type

user_defined_type]

In anonymous namespace

N12_GLOBAL__N_112in_anon_typeE

(anonymous namespace)::in_anon_type

{anonymous}::in_anon_type]

In ns3::{anonymous}::ns4 namespace

N3ns312_GLOBAL__N_13ns412in_anon_typeE

ns3::(anonymous namespace)::ns4::in_anon_type

ns3::{anonymous}::ns4::in_anon_type]

Template class

5templIsiE

templ<short, int>

templ<short int, int>]

Template class (full specialization)

5templIiiE

templ<int, int>

templ<int, int>]

Template class with template classes

5templIS_IcaES_Ii17user_defined_typeEE

templ<templ<char, signed char>, templ<int, user_defined_type> >

templ<templ<char, signed char>, templ<int, user_defined_type> >]


We have not show the "noRTTI & pretty_name" column in the table because it is almost equal to "noRTTI & raw_name" column.

[Warning] Warning

With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'.


PrevUpHomeNext