File: invoke_function_object.cpp

package info (click to toggle)
boost1.35 1.35.0-5
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 203,856 kB
  • ctags: 337,867
  • sloc: cpp: 938,683; xml: 56,847; ansic: 41,589; python: 18,999; sh: 11,566; makefile: 664; perl: 494; yacc: 456; asm: 353; csh: 6
file content (234 lines) | stat: -rw-r--r-- 7,798 bytes parent folder | download
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*=============================================================================
    Copyright (c) 2005-2006 João Abecasis
    Copyright (c) 2006-2007 Tobias Schwinger
  
    Use modification and distribution are subject to 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).
==============================================================================*/

#include <boost/fusion/functional/invocation/invoke_function_object.hpp>
#include <boost/detail/lightweight_test.hpp>

#include <boost/type_traits/is_same.hpp>

#include <memory>
#include <boost/noncopyable.hpp>

#include <boost/mpl/int.hpp>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/container/list.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/view/single_view.hpp>
#include <boost/fusion/view/iterator_range.hpp>
#include <boost/fusion/iterator/advance.hpp>
#include <boost/fusion/algorithm/transformation/join.hpp>

namespace mpl = boost::mpl;
namespace fusion = boost::fusion;

template <typename T>
inline T const & const_(T const & t)
{
    return t;
}

struct object {};
struct object_nc : boost::noncopyable {};

struct fobj
{
    // Handle nullary separately to exercise result_of support
    template <typename Sig> 
    struct result;

    template <class Self, typename T0>
    struct result< Self(T0) >
    {
        typedef int type;
    };

    template <class Self, typename T0, typename T1>
    struct result< Self(T0, T1) >
    {
        typedef int type;
    };

    template <class Self, typename T0, typename T1, typename T2>
    struct result< Self(T0, T1, T2) >
    {
        typedef int type;
    };

    int operator()()       { return 0; }
    int operator()() const { return 1; }

    int operator()(int i)       { return 2 + i; }
    int operator()(int i) const { return 3 + i; }

    int operator()(int i, object &)             { return 4 + i; }
    int operator()(int i, object &) const       { return 5 + i; }
    int operator()(int i, object const &)       { return 6 + i; }
    int operator()(int i, object const &) const { return 7 + i; }

    int operator()(int i, object &, object_nc &)       { return 10 + i; }
    int operator()(int i, object &, object_nc &) const { return 11 + i; }
};

struct nullary_fobj
{
    typedef int result_type;

    int operator()()       { return 0; }
    int operator()() const { return 1; }
};

struct fobj_nc
      : boost::noncopyable
{
    // Handle nullary separately to exercise result_of support
    template <typename T>
    struct result;

    template <class Self, typename T0>
    struct result< Self(T0) >
    {
        typedef int type;
    };
    
    int operator()(int i)       { return 14 + i; }
    int operator()(int i) const { return 15 + i; }
};

struct nullary_fobj_nc
      : boost::noncopyable
{
    typedef int result_type;

    int operator()()       { return 12; }
    int operator()() const { return 13; }
};


typedef int         element1_type;
typedef object      element2_type;
typedef object_nc & element3_type;

int         element1 = 100;
object      element2 = object();
object_nc   element3;

template <class Sequence>
void test_sequence_n(Sequence & seq, mpl::int_<0>)
{
    // Function Objects

    nullary_fobj f;
    BOOST_TEST(f () == fusion::invoke_function_object(f ,        seq ));
    BOOST_TEST(f () == fusion::invoke_function_object(f , const_(seq)));

    // Note: The function object is taken by value, so we request the copy
    // to be const with an explicit template argument. We can also request
    // the function object to be pased by reference...
    BOOST_TEST(const_(f)() == fusion::invoke_function_object<nullary_fobj const  >(const_(f),        seq ));
    BOOST_TEST(const_(f)() == fusion::invoke_function_object<nullary_fobj const &>(const_(f), const_(seq)));

    nullary_fobj_nc nc_f;
    // ...and we further ensure there is no copying in this case, using a
    // noncopyable function object.
    BOOST_TEST(nc_f () == fusion::invoke_function_object<nullary_fobj_nc &>(nc_f ,        seq ));
    BOOST_TEST(nc_f () == fusion::invoke_function_object<nullary_fobj_nc &>(nc_f , const_(seq)));
    BOOST_TEST(const_(nc_f)() == fusion::invoke_function_object<nullary_fobj_nc const &>(const_(nc_f),        seq ));
    BOOST_TEST(const_(nc_f)() == fusion::invoke_function_object<nullary_fobj_nc const &>(const_(nc_f), const_(seq)));
}

template <class Sequence>
void test_sequence_n(Sequence & seq, mpl::int_<1>)
{
    fobj f;
    BOOST_TEST(f(element1) == fusion::invoke_function_object(f , seq ));
    BOOST_TEST(f(element1) == fusion::invoke_function_object(f , const_(seq)));
    BOOST_TEST(const_(f)(element1) == fusion::invoke_function_object<fobj const  >(const_(f), seq ));
    BOOST_TEST(const_(f)(element1) == fusion::invoke_function_object<fobj const &>(const_(f), const_(seq)));

    fobj_nc nc_f;
    BOOST_TEST(nc_f(element1) == fusion::invoke_function_object<fobj_nc &>(nc_f, seq ));
    BOOST_TEST(nc_f(element1) == fusion::invoke_function_object<fobj_nc &>(nc_f, const_(seq)));
    BOOST_TEST(const_(nc_f)(element1) == fusion::invoke_function_object<fobj_nc const &>(const_(nc_f), seq ));
    BOOST_TEST(const_(nc_f)(element1) == fusion::invoke_function_object<fobj_nc const &>(const_(nc_f), const_(seq)));
}

template <class Sequence>
void test_sequence_n(Sequence & seq, mpl::int_<2>)
{
    fobj f;
    BOOST_TEST(f (element1, element2) == fusion::invoke_function_object(f , seq));
    BOOST_TEST(f (element1, const_(element2)) == fusion::invoke_function_object(f , const_(seq)));
    BOOST_TEST(const_(f)(element1, element2) == fusion::invoke_function_object<fobj const>(const_(f), seq));
    BOOST_TEST(const_(f)(element1, const_(element2)) == fusion::invoke_function_object<fobj const>(const_(f), const_(seq)));
}

template <class Sequence>
void test_sequence_n(Sequence & seq, mpl::int_<3>)
{
    fobj f;

    BOOST_TEST(f(element1, element2, element3) == fusion::invoke_function_object(f, seq));
    BOOST_TEST(const_(f)(element1, element2, element3) == fusion::invoke_function_object<fobj const>(const_(f), seq));
}

template <class Sequence>
void test_sequence(Sequence & seq)
{
    test_sequence_n(seq, mpl::int_<fusion::result_of::size<Sequence>::value>());
}

void result_type_tests()
{
    using boost::is_same;

    BOOST_TEST(( is_same< fusion::result_of::invoke_function_object< nullary_fobj, fusion::vector<> >::type, int >::value ));
    BOOST_TEST(( is_same< fusion::result_of::invoke_function_object< fobj, fusion::vector<element1_type> >::type, int >::value ));
    BOOST_TEST(( is_same< fusion::result_of::invoke_function_object< fobj, fusion::vector<element1_type,element2_type> >::type, int >::value ));
}


int main()
{
    result_type_tests();

    typedef fusion::vector<> vector0;
    typedef fusion::vector<element1_type> vector1;
    typedef fusion::vector<element1_type, element2_type> vector2;
    typedef fusion::vector<element1_type, element2_type, element3_type> vector3;

    vector0 v0;
    vector1 v1(element1);
    vector2 v2(element1, element2);
    vector3 v3(element1, element2, element3);

    test_sequence(v0);
    test_sequence(v1);
    test_sequence(v2);
    test_sequence(v3);

    typedef fusion::list<> list0;
    typedef fusion::list<element1_type> list1;
    typedef fusion::list<element1_type, element2_type> list2;
    typedef fusion::list<element1_type, element2_type, element3_type> list3;

    list0 l0;
    list1 l1(element1);
    list2 l2(element1, element2);
    list3 l3(element1, element2, element3);

    test_sequence(l0);
    test_sequence(l1);
    test_sequence(l2);
    test_sequence(l3);

    return boost::report_errors();
}