diff --git a/libs/type_index/doc/type_index.qbk b/libs/type_index/doc/type_index.qbk index b507e06..ef7d361 100644 --- a/libs/type_index/doc/type_index.qbk +++ b/libs/type_index/doc/type_index.qbk @@ -49,75 +49,22 @@ If you need to preserve `const`, `volatile` and references, use `boost::template [section Examples] -All code in the examples will work with and without RTTI support. -Class that allows to register a given type only once. -`` -class types_registry { - unordered_set types_; +[import ../examples/demangled_names.cpp] +[section Getting human readable and mangled type names] [type_index_names_example] [endsect] -public: - template - void add_type() { - type_index ti = type_id(); - std::cout << "Adding type " << ti << " to registry \n"; - if (!types_.insert(ti).second) - throw std::logic_error("Type " + ti.name_demangled() + " already registered"); - } +[import ../examples/registry.cpp] +[section Storing information about a type in container ] [type_index_registry_example] [endsect] - template - bool has_type() const { - return types_.cend() != types_.find(type_id()); - } -}; +[import ../examples/inheritance.cpp] +[section Getting through the inheritance to receive a real type name ] [type_index_derived_example] [endsect] -int main () { - types_registry tr; - tr.add_type(); - tr.add_type(); - - std::cout << "Has type int: " << tr.has_type() - << "\nHas type std::string: " << tr.has_type() - << '\n'; - - try { - tr.add_type(); // Will throw - } catch (const std::logic_error& e) { - // Will print "Type int already registered" - std::cout << e.what() << std::endl; - } -} - -`` - -This will output: -`` -Adding type int to registry -Adding type float to registry -Has type int: 1 -Has type std::string: 0 -`` - -Another example, this time checking for exact parameter match. -`my_unary_function` is a class, that stores a function with result type `ResultT` and any input parameter type. In `operator()`, it checks for input parameter match and then executes the stored function: - -`` -template -class my_unary_function { - void* function_ptr_; - template_index exact_param_t_; - ... - - template - ResultT operator()(ParamT& v) { - BOOST_ASSERT(exact_param_t_ == template_id_with_cvr()); - return (static_cast(function_ptr_))(v); - } -}; -`` +[import ../examples/exact_types_match.cpp] +[section Exact type match: storing type with const, volatile and reference ] [type_index_exact_type_match_example] [endsect] [endsect] + [xinclude autodoc.xml] diff --git a/libs/type_index/examples/demangled_names.cpp b/libs/type_index/examples/demangled_names.cpp new file mode 100644 index 0000000..89085c1 --- /dev/null +++ b/libs/type_index/examples/demangled_names.cpp @@ -0,0 +1,42 @@ +// Copyright 2013 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at .) + + +//[type_index_names_example +//`The following example shows how short (mangled) and human readable type names could be obtained from a type. +// Works with and without RTTI. + +#include +#include + +template +void foo(T) { + std::cout << "\n Short name: " << boost::type_id().name(); + std::cout << "\n Readable name: " << boost::type_id().name_demangled(); +} + +struct user_defined_type{}; + +int main() { + // Call to + foo(1); + // will output something like this: + // + // Short name: .H + // Readable name: int + + user_defined_type t; + foo(t); + // Will output: + // + // Short name: .?AUuser_defined_type@@ + // Readable name: struct user_defined_type +} + +// The example + + +//] [/type_index_names_example] diff --git a/libs/type_index/examples/exact_types_match.cpp b/libs/type_index/examples/exact_types_match.cpp new file mode 100644 index 0000000..349a1ef --- /dev/null +++ b/libs/type_index/examples/exact_types_match.cpp @@ -0,0 +1,56 @@ +// Copyright 2013 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at .) + +//[type_index_exact_type_match_example +/*` + The following example shows that `boost::template_index` 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 pointer to function and remembers the exact type of a parameter that function accepts. + When an attempt to call the stored function will be made, type of input parameter will be checked for exact match with initail/erased type of function. +*/ + +#include +#include + +class type_erased_unary_function { + void* function_ptr_; + boost::template_index exact_param_t_; + +public: + template + type_erased_unary_function(void(*ptr)(ParamT)) + : function_ptr_(ptr) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT` + , exact_param_t_(boost::template_id_with_cvr()) + {} + + template + void call(ParamT v) { + if (exact_param_t_ != boost::template_id_with_cvr()) { + throw std::runtime_error("Incorrect `ParamT`"); + } + + return (static_cast(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(i); // Will throw, because types `int&` and `int` missmatch + + assert(false); + } catch (const std::runtime_error& /*e*/) {} +} + +//] [/type_index_exact_type_match_example] diff --git a/libs/type_index/examples/inheritance.cpp b/libs/type_index/examples/inheritance.cpp new file mode 100644 index 0000000..01339f5 --- /dev/null +++ b/libs/type_index/examples/inheritance.cpp @@ -0,0 +1,32 @@ +// Copyright 2013 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at .) + +//[type_index_derived_example +/*` + The following example shows that `boost::type_index` is able to store the real type, successfully getting through + all the inheritances. + Example works with RTTI only. +*/ + +#include +#include + +struct A { virtual ~A(){} }; +struct B: public A {}; +struct C: public B {}; + +void print_real_type(const A& a) { + std::cout << boost::type_id_rtti_only(a).name_demangled() << '\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` +} + +//] [/type_index_derived_example] diff --git a/libs/type_index/examples/registry.cpp b/libs/type_index/examples/registry.cpp new file mode 100644 index 0000000..a0bcc02 --- /dev/null +++ b/libs/type_index/examples/registry.cpp @@ -0,0 +1,36 @@ +// Copyright 2013 Antony Polukhin + +// Distributed under the Boost Software License, Version 1.0. +// (See the accompanying file LICENSE_1_0.txt +// or a copy at .) + +//[type_index_registry_example +/*` + The following example shows how an information about a type could be stored. + Example works with and without RTTI. +*/ + +#include +#include +#include + +int main() { + boost::unordered_set types; + + // Storing some `boost::type_info`s + types.insert(boost::type_id()); + types.insert(boost::type_id()); + + // `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::type_id()).second; + assert(!is_inserted); + assert(types.erase(boost::type_id()) == 1); + + // We have erased the `float` type, only `int` remains + assert(*types.begin() == boost::type_id()); +} + +//] [/type_index_registry_example] diff --git a/libs/type_index/test/Jamfile.v2 b/libs/type_index/test/Jamfile.v2 index 79dc426..02fdff3 100644 --- a/libs/type_index/test/Jamfile.v2 +++ b/libs/type_index/test/Jamfile.v2 @@ -21,5 +21,14 @@ test-suite type_index [ run testing_both_no_rtti.cpp : : : off ] [ run testing_minimal.cpp ] [ run testing_minimal_no_rtti.cpp : : : off ] + # Examples that must work even with RTTI disabled + [ run ../examples/registry.cpp : : : off ] + [ run ../examples/exact_types_match.cpp : : : off ] + [ run ../examples/demangled_names.cpp : : : off ] ; - + +# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite. +for local p in [ glob ../examples/*.cpp ] +{ + type_index += [ run $(p) ] ; +}