forked from mcoquet642/AliceO2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_mpl_tools.cxx
More file actions
161 lines (141 loc) · 5.76 KB
/
test_mpl_tools.cxx
File metadata and controls
161 lines (141 loc) · 5.76 KB
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
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
// @file test_mpl_tools.cxx
// @author Matthias Richter
// @since 2017-06-22
// @brief Test program for MPL tools
#define BOOST_TEST_MODULE Utility test
#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include "../include/Algorithm/mpl_tools.h"
#include <boost/mpl/size.hpp>
#include <boost/type.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/string.hpp> // see note below
#include <iostream>
#include <iomanip>
#include <vector>
#include <type_traits>
// FIXME: mpl/string.hpp required to be included to avoid compilation error
// error: no matching function for call to ‘assertion_failed ...' in the mpl::for_each
// implementation (BOOST_MPL_ASSERT check). Not fully understood as simply including
// mpl/assert.hpp does not help. Maybe it's an inconssitency in the do_typewrap meta
// program
namespace bmpl = boost::mpl;
// defining a list of known data types
using knowntypes = bmpl::vector<float, double, long double, short, long>;
// get the index of an element in a type sequence
template <typename Iterator, typename End, typename Element, typename T, int Count = 0>
struct type_index {
using type = typename bmpl::if_<typename std::is_same<Element, T>::type, bmpl::int_<Count>, //
typename type_index<typename bmpl::next<Iterator>::type, End, //
typename bmpl::deref<Iterator>::type, //
T, //
Count + 1 //
>::type>::type; //
static const int value = type::value;
};
// termination condition
template <typename End, typename Element, typename T, int Count>
struct type_index<End, End, Element, T, Count> {
using type = typename bmpl::if_<typename std::is_same<Element, T>::type, //
bmpl::int_<Count>, //
bmpl::int_<Count + 1>>::type; //
static const int value = type::value;
};
// Initializer for the inner type wrapper, use the index in the
// list of known types
template <typename T>
struct Initializer {
static const int value = type_index<typename bmpl::begin<knowntypes>::type, //
typename bmpl::end<knowntypes>::type, //
bmpl::void_, //
T>::value; //
};
// the inner class for the fold
// the data member is initialized with the index in the list
// of known data types which can be wrapped by the class
template <typename T>
class Model
{
public:
using value_type = T;
Model() : mData(Initializer<value_type>::value) {}
~Model() = default;
friend std::ostream& operator<<(std::ostream& stream, const Model& rhs)
{
stream << "Model ";
stream << rhs.mData;
return stream;
}
private:
T mData;
};
// the outer class for the fold
template <typename T>
class Codec
{
public:
using value_type = T;
using wrapped_type = typename T::value_type;
Codec() = default;
~Codec() = default;
friend std::ostream& operator<<(std::ostream& stream, const Codec& rhs)
{
stream << "Codec ";
stream << rhs.mData;
return stream;
}
private:
T mData;
};
// simple functor for printing class/type info
struct checktype {
template <typename T>
void operator()(const T& v)
{
std::cout << v << std::endl;
std::cout << "is integral: " << std::is_integral<T>::value << std::endl;
}
};
BOOST_AUTO_TEST_CASE(test_mpl_fold)
{
using types = bmpl::vector<long, float, short, double, float, long, long double>;
std::cout << std::endl
<< "checking types:" << std::endl;
bmpl::for_each<types>(checktype());
// bmpl::fold recursivly applies the elements of the list to the previous result
// placeholder _2 refers to the element, placeholder _1 to the previous result
// or initial condition for the first element
// in this particular example, the initial condition is a data type for in 0,
// which is incremented with bmpl::next if the type of the element is float
using number_of_floats =
bmpl::fold<types, bmpl::int_<0>, bmpl::if_<std::is_floating_point<_2>, bmpl::next<_1>, _1>>::type;
// using the meta program, this can be a static_assert
static_assert(number_of_floats::value == 4, "inconsistent number of float values in the type definition");
// wrapping all elements into the Model class
std::cout << std::endl
<< "checking first fold:" << std::endl;
using models = o2::mpl::do_typewrap<types, bmpl::lambda<Model<_>>::type>::type;
bmpl::for_each<models>(checktype());
// wrapping all elements into the Codec class
std::cout << std::endl
<< "checking second fold:" << std::endl;
using codecs = o2::mpl::do_typewrap<models, bmpl::lambda<Codec<_>>::type>::type;
bmpl::for_each<codecs>(checktype());
}