zip.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // (C) Copyright Gennadiy Rozental 2001.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. /// @file
  8. /// Defines monomorphic dataset based on zipping of 2 other monomorphic datasets
  9. // ***************************************************************************
  10. #ifndef BOOST_TEST_DATA_MONOMORPHIC_ZIP_HPP_102211GER
  11. #define BOOST_TEST_DATA_MONOMORPHIC_ZIP_HPP_102211GER
  12. // Boost.Test
  13. #include <boost/test/data/config.hpp>
  14. #if !defined(BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
  15. #include <boost/test/data/monomorphic/fwd.hpp>
  16. #include <boost/test/data/monomorphic/sample_merge.hpp>
  17. #include <boost/test/detail/suppress_warnings.hpp>
  18. namespace boost {
  19. namespace unit_test {
  20. namespace data {
  21. namespace monomorphic {
  22. // ************************************************************************** //
  23. // ************** zip ************** //
  24. // ************************************************************************** //
  25. //! Zip datasets
  26. //!
  27. //! A zip of two datasets is a dataset whose arity is the sum of the operand datasets arity. The size is given by
  28. //! the function creating the instance (see @c operator^ on datasets).
  29. template<typename DataSet1, typename DataSet2>
  30. class zip {
  31. typedef typename boost::decay<DataSet1>::type dataset1_decay;
  32. typedef typename boost::decay<DataSet2>::type dataset2_decay;
  33. typedef typename dataset1_decay::iterator dataset1_iter;
  34. typedef typename dataset2_decay::iterator dataset2_iter;
  35. public:
  36. enum { arity = dataset1_decay::arity + dataset2_decay::arity };
  37. struct iterator {
  38. // Constructor
  39. explicit iterator( dataset1_iter iter1, dataset2_iter iter2 )
  40. : m_iter1( std::move( iter1 ) )
  41. , m_iter2( std::move( iter2 ) )
  42. {}
  43. using iterator_sample = decltype(
  44. sample_merge( *std::declval<dataset1_iter>(),
  45. *std::declval<dataset2_iter>()) );
  46. // forward iterator interface
  47. auto operator*() const -> iterator_sample {
  48. return sample_merge( *m_iter1, *m_iter2 );
  49. }
  50. void operator++() { ++m_iter1; ++m_iter2; }
  51. private:
  52. // Data members
  53. dataset1_iter m_iter1;
  54. dataset2_iter m_iter2;
  55. };
  56. typedef typename iterator::iterator_sample sample;
  57. //! Constructor
  58. //!
  59. //! The datasets are moved and not copied.
  60. zip( DataSet1&& ds1, DataSet2&& ds2/*, data::size_t size*/ )
  61. : m_ds1( std::forward<DataSet1>( ds1 ) )
  62. , m_ds2( std::forward<DataSet2>( ds2 ) )
  63. //, m_size( size )
  64. {}
  65. //! Move constructor
  66. zip( zip&& j )
  67. : m_ds1( std::forward<DataSet1>( j.m_ds1 ) )
  68. , m_ds2( std::forward<DataSet2>( j.m_ds2 ) )
  69. //, m_size( j.m_size )
  70. {}
  71. // dataset interface
  72. data::size_t size() const { return zip_size(); }
  73. iterator begin() const { return iterator( m_ds1.begin(), m_ds2.begin() ); }
  74. private:
  75. // Data members
  76. DataSet1 m_ds1;
  77. DataSet2 m_ds2;
  78. //data::size_t m_size;
  79. //! Handles the sise of the resulting zipped dataset.
  80. data::size_t zip_size() const
  81. {
  82. data::size_t ds1_size = m_ds1.size();
  83. data::size_t ds2_size = m_ds2.size();
  84. if( ds1_size == ds2_size )
  85. return ds1_size;
  86. if( ds1_size == 1 || ds1_size.is_inf() )
  87. return ds2_size;
  88. if( ds2_size == 1 || ds2_size.is_inf() )
  89. return ds1_size;
  90. BOOST_TEST_DS_ERROR( "Can't zip datasets of different sizes" );
  91. }
  92. };
  93. //____________________________________________________________________________//
  94. //! Zipped datasets results in a dataset.
  95. template<typename DataSet1, typename DataSet2>
  96. struct is_dataset<zip<DataSet1,DataSet2>> : mpl::true_ {};
  97. //____________________________________________________________________________//
  98. namespace result_of {
  99. //! Result type of the zip operator.
  100. template<typename DS1Gen, typename DS2Gen>
  101. struct zip {
  102. typedef monomorphic::zip<typename DS1Gen::type,typename DS2Gen::type> type;
  103. };
  104. } // namespace result_of
  105. //____________________________________________________________________________//
  106. //! Overload operator for zip support
  107. template<typename DataSet1, typename DataSet2>
  108. inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
  109. result_of::zip<mpl::identity<DataSet1>,mpl::identity<DataSet2>>
  110. >::type
  111. operator^( DataSet1&& ds1, DataSet2&& ds2 )
  112. {
  113. return zip<DataSet1,DataSet2>( std::forward<DataSet1>( ds1 ),
  114. std::forward<DataSet2>( ds2 )/*,
  115. ds_detail::zip_size( ds1, ds2 )*/ );
  116. }
  117. //____________________________________________________________________________//
  118. //! @overload boost::unit_test::data::monomorphic::operator^()
  119. template<typename DataSet1, typename DataSet2>
  120. inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && !is_dataset<DataSet2>::value,
  121. result_of::zip<mpl::identity<DataSet1>,data::result_of::make<DataSet2>>
  122. >::type
  123. operator^( DataSet1&& ds1, DataSet2&& ds2 )
  124. {
  125. return std::forward<DataSet1>( ds1 ) ^ data::make( std::forward<DataSet2>( ds2 ) );
  126. }
  127. //____________________________________________________________________________//
  128. //! @overload boost::unit_test::data::monomorphic::operator^()
  129. template<typename DataSet1, typename DataSet2>
  130. inline typename boost::lazy_enable_if_c<!is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
  131. result_of::zip<data::result_of::make<DataSet1>,mpl::identity<DataSet2>>
  132. >::type
  133. operator^( DataSet1&& ds1, DataSet2&& ds2 )
  134. {
  135. return data::make( std::forward<DataSet1>( ds1 ) ) ^ std::forward<DataSet2>( ds2 );
  136. }
  137. } // namespace monomorphic
  138. } // namespace data
  139. } // namespace unit_test
  140. } // namespace boost
  141. #include <boost/test/detail/enable_warnings.hpp>
  142. #endif // BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE
  143. #endif // BOOST_TEST_DATA_MONOMORPHIC_ZIP_HPP_102211GER