customize_use_as_container.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Hartmut Kaiser
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #include <boost/config/warning_disable.hpp>
  8. //[customize_karma_use_as_container_includes
  9. #include <boost/spirit/include/karma.hpp>
  10. #include <iostream>
  11. #include <string>
  12. #include <vector>
  13. //]
  14. ///////////////////////////////////////////////////////////////////////////////
  15. //[customize_karma_use_as_container_data
  16. namespace client
  17. {
  18. struct use_as_container
  19. {
  20. // Expose a pair holding a pointer to the use_as_container and to the
  21. // current element as our iterator.
  22. // We intentionally leave out having it a 'operator==()' to demonstrate
  23. // the use of the 'compare_iterators' customization point.
  24. struct iterator
  25. {
  26. iterator(use_as_container const* container, int const* current)
  27. : container_(container), current_(current)
  28. {}
  29. use_as_container const* container_;
  30. int const* current_;
  31. };
  32. // expose 'int' as the type of each generated element
  33. typedef int type;
  34. use_as_container(int value1, int value2, int value3)
  35. : value1_(value1), value2_(value2), value3_(value3)
  36. {}
  37. int value1_;
  38. std::string dummy1_; // insert some unrelated data
  39. int value2_;
  40. std::string dummy2_; // insert some more unrelated data
  41. int value3_;
  42. };
  43. }
  44. //]
  45. //[customize_karma_use_as_container_traits
  46. // All specializations of attribute customization points have to be placed into
  47. // the namespace boost::spirit::traits.
  48. //
  49. // Note that all templates below are specialized using the 'const' type.
  50. // This is necessary as all attributes in Karma are 'const'.
  51. namespace boost { namespace spirit { namespace traits
  52. {
  53. // The specialization of the template 'is_container<>' will tell the
  54. // library to treat the type 'client::use_as_container' as a
  55. // container holding the items to generate output from.
  56. template <>
  57. struct is_container<client::use_as_container const>
  58. : mpl::true_
  59. {};
  60. // The specialization of the template 'container_iterator<>' will be
  61. // invoked by the library to evaluate the iterator type to be used
  62. // for iterating the data elements in the container. We simply return
  63. // the type of the iterator exposed by the embedded 'std::vector<int>'.
  64. template <>
  65. struct container_iterator<client::use_as_container const>
  66. {
  67. typedef client::use_as_container::iterator type;
  68. };
  69. // The specialization of the templates 'begin_container<>' and
  70. // 'end_container<>' below will be used by the library to get the iterators
  71. // pointing to the begin and the end of the data to generate output from.
  72. //
  73. // The passed argument refers to the attribute instance passed to the list
  74. // generator.
  75. template <>
  76. struct begin_container<client::use_as_container const>
  77. {
  78. static client::use_as_container::iterator
  79. call(client::use_as_container const& c)
  80. {
  81. return client::use_as_container::iterator(&c, &c.value1_);
  82. }
  83. };
  84. template <>
  85. struct end_container<client::use_as_container const>
  86. {
  87. static client::use_as_container::iterator
  88. call(client::use_as_container const& c)
  89. {
  90. return client::use_as_container::iterator(&c, (int const*)0);
  91. }
  92. };
  93. }}}
  94. //]
  95. //[customize_karma_use_as_container_iterator_traits
  96. // All specializations of attribute customization points have to be placed into
  97. // the namespace boost::spirit::traits.
  98. namespace boost { namespace spirit { namespace traits
  99. {
  100. // The specialization of the template 'deref_iterator<>' will be used to
  101. // dereference the iterator associated with our counter data structure.
  102. template <>
  103. struct deref_iterator<client::use_as_container::iterator>
  104. {
  105. typedef client::use_as_container::type type;
  106. static type call(client::use_as_container::iterator const& it)
  107. {
  108. return *it.current_;
  109. }
  110. };
  111. template <>
  112. struct next_iterator<client::use_as_container::iterator>
  113. {
  114. static void call(client::use_as_container::iterator& it)
  115. {
  116. if (it.current_ == &it.container_->value1_)
  117. it.current_ = &it.container_->value2_;
  118. else if (it.current_ == &it.container_->value2_)
  119. it.current_ = &it.container_->value3_;
  120. else
  121. it.current_ = 0;
  122. }
  123. };
  124. template <>
  125. struct compare_iterators<client::use_as_container::iterator>
  126. {
  127. static bool call(client::use_as_container::iterator const& it1
  128. , client::use_as_container::iterator const& it2)
  129. {
  130. return it1.current_ == it2.current_ &&
  131. it1.container_ == it2.container_;
  132. }
  133. };
  134. }}}
  135. //]
  136. ///////////////////////////////////////////////////////////////////////////////
  137. namespace karma = boost::spirit::karma;
  138. int main()
  139. {
  140. //[customize_karma_use_as_container
  141. client::use_as_container d2 (1, 2, 3);
  142. // use the instance of a 'client::use_as_container' instead of a STL vector
  143. std::cout << karma::format(karma::int_ % ", ", d2) << std::endl; // prints: '1, 2, 3'
  144. //]
  145. return 0;
  146. }