util_dynamic_type_disp.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2015.
  3. * Distributed under the Boost Software License, Version 1.0.
  4. * (See accompanying file LICENSE_1_0.txt or copy at
  5. * http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. /*!
  8. * \file util_dynamic_type_disp.cpp
  9. * \author Andrey Semashev
  10. * \date 09.01.2009
  11. *
  12. * \brief This header contains tests for the dynamic type dispatcher.
  13. */
  14. #define BOOST_TEST_MODULE util_dynamic_type_disp
  15. #include <string>
  16. #include <boost/bind.hpp>
  17. #include <boost/test/unit_test.hpp>
  18. #include <boost/test/tools/floating_point_comparison.hpp>
  19. #include <boost/log/utility/type_dispatch/dynamic_type_dispatcher.hpp>
  20. namespace logging = boost::log;
  21. namespace {
  22. // A simple attribute value
  23. template< typename T >
  24. struct my_value
  25. {
  26. T m_Value;
  27. explicit my_value(T const& value) : m_Value(value) {}
  28. // The function passes the contained type into the dispatcher
  29. bool dispatch(logging::type_dispatcher& dispatcher)
  30. {
  31. logging::type_dispatcher::callback< T > callback = dispatcher.get_callback< T >();
  32. if (callback)
  33. {
  34. callback(m_Value);
  35. return true;
  36. }
  37. else
  38. return false;
  39. }
  40. };
  41. struct my_visitor
  42. {
  43. enum type_expected
  44. {
  45. none_expected,
  46. int_expected,
  47. double_expected,
  48. string_expected
  49. };
  50. my_visitor() : m_Expected(none_expected), m_Int(0), m_Double(0.0) {}
  51. void set_expected()
  52. {
  53. m_Expected = none_expected;
  54. }
  55. void set_expected(int value)
  56. {
  57. m_Expected = int_expected;
  58. m_Int = value;
  59. }
  60. void set_expected(double value)
  61. {
  62. m_Expected = double_expected;
  63. m_Double = value;
  64. }
  65. void set_expected(std::string const& value)
  66. {
  67. m_Expected = string_expected;
  68. m_String = value;
  69. }
  70. // Implement visitation logic for all supported types
  71. void on_int(int const& value)
  72. {
  73. BOOST_CHECK_EQUAL(m_Expected, int_expected);
  74. BOOST_CHECK_EQUAL(m_Int, value);
  75. }
  76. void on_double(double const& value)
  77. {
  78. BOOST_CHECK_EQUAL(m_Expected, double_expected);
  79. BOOST_CHECK_CLOSE(m_Double, value, 0.001);
  80. }
  81. void on_string(std::string const& value)
  82. {
  83. BOOST_CHECK_EQUAL(m_Expected, string_expected);
  84. BOOST_CHECK_EQUAL(m_String, value);
  85. }
  86. private:
  87. type_expected m_Expected;
  88. int m_Int;
  89. double m_Double;
  90. std::string m_String;
  91. };
  92. } // namespace
  93. // The test checks that general functionality works
  94. BOOST_AUTO_TEST_CASE(type_dispatch)
  95. {
  96. my_visitor vis;
  97. logging::dynamic_type_dispatcher disp;
  98. // Register type visitors
  99. disp.register_type< int >(boost::bind(&my_visitor::on_int, &vis, _1));
  100. disp.register_type< double >(boost::bind(&my_visitor::on_double, &vis, _1));
  101. BOOST_CHECK(disp.registered_types_count() == 2);
  102. // Right now strings are not supported by the dispatcher
  103. my_value< std::string > val1("Hello world!");
  104. BOOST_CHECK(!val1.dispatch(disp));
  105. // And now they are
  106. disp.register_type< std::string >(boost::bind(&my_visitor::on_string, &vis, _1));
  107. BOOST_CHECK(disp.registered_types_count() == 3);
  108. vis.set_expected(val1.m_Value);
  109. BOOST_CHECK(val1.dispatch(disp));
  110. my_value< double > val2(1.2);
  111. vis.set_expected(val2.m_Value);
  112. BOOST_CHECK(val2.dispatch(disp));
  113. // This one is not supported
  114. my_value< float > val3(static_cast< float >(-4.3));
  115. vis.set_expected();
  116. BOOST_CHECK(!val3.dispatch(disp));
  117. }