| // Copyright 2013-2021 Antony Polukhin |
| |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See the accompanying file LICENSE_1_0.txt |
| // or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) |
| |
| //[type_index_exact_type_match_example |
| /*` |
| 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 <cstdlib> |
| |
| //<- |
| // Making `#include <cassert>` visible in docs, while actually using hand-made check |
| // instead of `assert`. This is required to verify correct behavior even if NDEBUG |
| // is defined and to avoid `unused local variable` warnings with defined NDEBUG. |
| #ifdef assert |
| # undef assert |
| #endif |
| #define assert(X) if (!(X)) std::exit(__LINE__) |
| /* !Comment block is not closed intentionaly! |
| //-> |
| #include <cassert> |
| //<- |
| !Closing comment block! */ |
| //-> |
| |
| 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*/) {} |
| } |
| |
| //] [/type_index_exact_type_match_example] |