blob: 05eaa7adaf6a349dfeb140db77d0d1c0156ddd96 [file] [log] [blame]
// 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]