summaryrefslogtreecommitdiff
path: root/boost/test/data/monomorphic/join.hpp
blob: f817994dd3fc479fba648b0c91dc79b99434b621 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//  (C) Copyright Gennadiy Rozental 2001.
//  Distributed under the Boost Software License, Version 1.0.
//  (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/test for the library home page.
//
//! @file
//! Defines dataset join operation
// ***************************************************************************

#ifndef BOOST_TEST_DATA_MONOMORPHIC_JOIN_HPP_112711GER
#define BOOST_TEST_DATA_MONOMORPHIC_JOIN_HPP_112711GER

// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>

#include <boost/test/detail/suppress_warnings.hpp>

//____________________________________________________________________________//

namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {

// ************************************************************************** //
// **************                      join                    ************** //
// ************************************************************************** //

//! Defines a new dataset from the concatenation of two datasets
//!
//! The size of the resulting dataset is the sum of the two underlying datasets. The arity of the datasets
//! should match.
template<typename DataSet1, typename DataSet2>
class join {
    typedef typename boost::decay<DataSet1>::type   dataset1_decay;
    typedef typename boost::decay<DataSet2>::type   dataset2_decay;

    typedef typename dataset1_decay::iterator       dataset1_iter;
    typedef typename dataset2_decay::iterator       dataset2_iter;
public:
    typedef typename dataset1_decay::sample         sample;

    enum { arity = dataset1_decay::arity };

    struct iterator {
        // Constructor
        explicit    iterator( dataset1_iter it1, dataset2_iter it2, data::size_t first_size )
        : m_it1( std::move( it1 ) )
        , m_it2( std::move( it2 ) )
        , m_first_size( first_size )
        {}

        // forward iterator interface
        sample const&       operator*() const   { return m_first_size > 0 ? *m_it1 : *m_it2; }
        void                operator++()        { if( m_first_size > 0 ) { --m_first_size; ++m_it1; } else ++m_it2; }

    private:
        // Data members
        dataset1_iter       m_it1;
        dataset2_iter       m_it2;
        data::size_t        m_first_size;
    };

    //! Constructor 
    join( DataSet1&& ds1, DataSet2&& ds2 )
    : m_ds1( std::forward<DataSet1>( ds1 ) )
    , m_ds2( std::forward<DataSet2>( ds2 ) )
    {}

    //! Move constructor
    join( join&& j )
    : m_ds1( std::forward<DataSet1>( j.m_ds1 ) )
    , m_ds2( std::forward<DataSet2>( j.m_ds2 ) )
    {}

    //! dataset interface
    data::size_t    size() const    { return m_ds1.size() + m_ds2.size(); }
    iterator        begin() const   { return iterator( m_ds1.begin(), m_ds2.begin(), m_ds1.size() ); }

private:
    // Data members
    DataSet1        m_ds1;
    DataSet2        m_ds2;
};

//____________________________________________________________________________//

// A joined dataset  is a dataset.
template<typename DataSet1, typename DataSet2>
struct is_dataset<join<DataSet1,DataSet2>> : mpl::true_ {};

//____________________________________________________________________________//

namespace result_of {

//! Result type of the join operation on datasets.
template<typename DataSet1Gen, typename DataSet2Gen>
struct join {
    typedef monomorphic::join<typename DataSet1Gen::type,typename DataSet2Gen::type> type;
};

} // namespace result_of

//____________________________________________________________________________//

template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
                                        result_of::join<mpl::identity<DataSet1>,mpl::identity<DataSet2>>
>::type
operator+( DataSet1&& ds1, DataSet2&& ds2 )
{
    return join<DataSet1,DataSet2>( std::forward<DataSet1>( ds1 ),  std::forward<DataSet2>( ds2 ) );
}

//____________________________________________________________________________//

template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && !is_dataset<DataSet2>::value,
                                        result_of::join<mpl::identity<DataSet1>,data::result_of::make<DataSet2>>
>::type
operator+( DataSet1&& ds1, DataSet2&& ds2 )
{
    return std::forward<DataSet1>( ds1 ) + data::make( std::forward<DataSet2>( ds2 ) );
}

//____________________________________________________________________________//

template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<!is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
                                        result_of::join<data::result_of::make<DataSet1>,mpl::identity<DataSet2>>
>::type
operator+( DataSet1&& ds1, DataSet2&& ds2 )
{
    return data::make( std::forward<DataSet1>(ds1) ) + std::forward<DataSet2>( ds2 );
}

} // namespace monomorphic
} // namespace data
} // namespace unit_test
} // namespace boost

#include <boost/test/detail/enable_warnings.hpp>

#endif // BOOST_TEST_DATA_MONOMORPHIC_JOIN_HPP_112711GER