exact_types_match.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright 2013-2019 Antony Polukhin
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See the accompanying file LICENSE_1_0.txt
  4. // or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
  5. //[type_index_exact_type_match_example
  6. /*`
  7. The following example shows that `type_index` (and `type_info`) is able to store the exact type,
  8. without stripping const, volatile and references. Example works with and without RTTI.
  9. In this example we'll create a class that stores a pointer to function and remembers the exact type of the
  10. parameter the function accepts. When the call to the bound function is made, he actual input parameter
  11. type is checked against the stored parameter type and an exception is thrown in case of mismatch.
  12. */
  13. #include <boost/type_index.hpp>
  14. #include <iostream>
  15. #include <stdexcept>
  16. #include <cstdlib>
  17. //<-
  18. // Making `#include <cassert>` visible in docs, while actually using hand-made check
  19. // instead of `assert`. This is required to verify correct behavior even if NDEBUG
  20. // is defined and to avoid `unused local variable` warnings with defined NDEBUG.
  21. #ifdef assert
  22. # undef assert
  23. #endif
  24. #define assert(X) if (!(X)) std::exit(__LINE__)
  25. /* !Comment block is not closed intentionaly!
  26. //->
  27. #include <cassert>
  28. //<-
  29. !Closing comment block! */
  30. //->
  31. class type_erased_unary_function {
  32. void* function_ptr_;
  33. boost::typeindex::type_index exact_param_t_;
  34. public:
  35. template <class ParamT>
  36. type_erased_unary_function(void(*ptr)(ParamT))
  37. : function_ptr_(reinterpret_cast<void*>(ptr)) // ptr - is a pointer to function returning `void` and accepting parameter of type `ParamT`
  38. , exact_param_t_(boost::typeindex::type_id_with_cvr<ParamT>())
  39. {}
  40. template <class ParamT>
  41. void call(ParamT v) {
  42. if (exact_param_t_ != boost::typeindex::type_id_with_cvr<ParamT>()) {
  43. throw std::runtime_error("Incorrect `ParamT`");
  44. }
  45. return (reinterpret_cast<void(*)(ParamT)>(function_ptr_))(v);
  46. }
  47. };
  48. void foo(int){}
  49. int main() {
  50. type_erased_unary_function func(&foo);
  51. func.call(100); // OK, `100` has type `int`
  52. try {
  53. int i = 100;
  54. // An attempt to convert stored function to a function accepting reference
  55. func.call<int&>(i); // Will throw, because types `int&` and `int` mismatch
  56. assert(false);
  57. } catch (const std::runtime_error& /*e*/) {}
  58. }
  59. //] [/type_index_exact_type_match_example]