std_concept.hpp 8.48 KB
Newer Older
1
// Software License for MTL
2
//
3
4
5
6
7
// Copyright (c) 2007 The Trustees of Indiana University.
//               2008 Dresden University of Technology and the Trustees of Indiana University.
//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
// All rights reserved.
// Authors: Peter Gottschling and Andrew Lumsdaine
8
//
9
// This file is part of the Matrix Template Library
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
// See also license.mtl.txt in the distribution.

#ifndef MTL_STD_CONCEPT_INCLUDE
#define MTL_STD_CONCEPT_INCLUDE

#ifdef __GXX_CONCEPTS__
#  include <concepts>
#else
// Use Joel de Guzman's return type deduction
#  include <boost/numeric/ublas/detail/returntype_deduction.hpp>
#  include <boost/mpl/at.hpp>
#  include <boost/numeric/linear_algebra/pseudo_concept.hpp>
#endif

// #include <boost/numeric/mtl/utility/is_what.hpp>         -> leads to cyclic inclusions
// #include <boost/numeric/mtl/operation/mult_result.hpp>

namespace mtl {

/**
 * \defgroup Concepts Concepts
 */
/*@{*/

#ifdef __GXX_CONCEPTS__

    // Stay with the old names (for the moment)

    auto concept Addable<typename T, typename U = T> : std::HasPlus<T, U> {}
    auto concept Subtractable<typename T, typename U = T> : std::HasMinus<T, U> {}
    auto concept Multiplicable<typename T, typename U = T> : std::HasMultiply<T, U> {}
    auto concept Divisible<typename T, typename U = T> : std::HasDivide<T, U> {}

#if 0
    using std::Addable;
    using std::Subtractable;
    using std::Multiplicable;

    auto concept Divisible<typename T, typename U = T>
    {
	typename result_type;
	result_type operator/(const T& t, const U& u);
    };
#endif

#else // without concepts

    // Use Joel de Guzman's return type deduction
    // Adapted from uBLAS
60
    // Differences:
61
62
63
64
    //   - Separate types for all operations
    //   - result_type like in concept

    /// Concept Addable: Binary operation
65
    /** In concept-free compilations also used for return type deduction */
66
67
68
69
70
71
72
73
74
75
    template<class X, class Y>
    class Addable
    {
	typedef boost::numeric::ublas::type_deduction_detail::base_result_of<X, Y> base_type;
	static typename base_type::x_type x;
	static typename base_type::y_type y;
	static const std::size_t size = sizeof (
               boost::numeric::ublas::type_deduction_detail::test<
                    typename base_type::x_type
                  , typename base_type::y_type
76
                >(x + y)
77
78
79
80
81
82
83
84
85
86
87
88
	     );

	static const std::size_t index = (size / sizeof (char)) - 1;
	typedef typename boost::mpl::at_c<
	    typename base_type::types, index>::type id;
    public:
	/// Result of addition
	typedef typename id::type result_type;
    };


    /// Concept Subtractable: Binary operation
89
    /** In concept-free compilations also used for return type deduction */
90
91
92
93
94
95
96
97
98
99
    template<class X, class Y>
    class Subtractable
    {
        typedef boost::numeric::ublas::type_deduction_detail::base_result_of<X, Y> base_type;
        static typename base_type::x_type x;
        static typename base_type::y_type y;
        static const std::size_t size = sizeof (
                   boost::numeric::ublas::type_deduction_detail::test<
                        typename base_type::x_type
                      , typename base_type::y_type
100
                    >(x - y)
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
                );

        static const std::size_t index = (size / sizeof (char)) - 1;
        typedef typename boost::mpl::at_c<
    	typename base_type::types, index>::type id;
    public:
	/// Result of subtraction
        typedef typename id::type result_type;
    };

#if 0 // doesn't work
    template<class X, class Y>
    class Multiplicable_aux<X, Y, true>
    {
	typedef typename mtl::traits::mult_result<X, Y>::type type;
    };

    /// Concept Multiplicable: Binary operation
119
    /** In concept-free compilations also used for return type deduction */
120
121
122
123
124
125
126
127
128
129
    template<class X, class Y, bool B>
    class Multiplicable_aux
    {
        typedef boost::numeric::ublas::type_deduction_detail::base_result_of<X, Y> base_type;
        static typename base_type::x_type x;
        static typename base_type::y_type y;
        static const std::size_t size = sizeof (
                   boost::numeric::ublas::type_deduction_detail::test<
                        typename base_type::x_type
                      , typename base_type::y_type
130
                    >(x * y)
131
132
133
134
135
136
137
138
139
                );

        static const std::size_t index = (size / sizeof (char)) - 1;
        typedef typename boost::mpl::at_c<
    	typename base_type::types, index>::type id;
    public:
	/// Result of multiplication
        typedef typename id::type result_type;
    };
140

141
    /// Concept Multiplicable: Binary operation
142
    /** In concept-free compilations also used for return type deduction */
143
144
145
146
147
148
149
    template<class X, class Y>
    class Multiplicable
      : Multiplicable_aux<X, Y, mtl::traits::is_scalar<X>::value && mtl::traits::is_scalar<Y>::value>
    {};
#endif

    /// Concept Multiplicable: Binary operation
150
    /** In concept-free compilations also used for return type deduction */
151
152
153
154
155
156
157
158
159
160
    template<class X, class Y>
    class Multiplicable
    {
        typedef boost::numeric::ublas::type_deduction_detail::base_result_of<X, Y> base_type;
        static typename base_type::x_type x;
        static typename base_type::y_type y;
        static const std::size_t size = sizeof (
                   boost::numeric::ublas::type_deduction_detail::test<
                        typename base_type::x_type
                      , typename base_type::y_type
161
                    >(x * y)
162
163
164
165
166
167
168
169
170
171
172
                );

        static const std::size_t index = (size / sizeof (char)) - 1;
        typedef typename boost::mpl::at_c<
    	typename base_type::types, index>::type id;
    public:
	/// Result of multiplication
        typedef typename id::type result_type;
    };

    /// Concept Divisible: Binary operation
173
    /** In concept-free compilations also used for return type deduction */
174
175
176
177
178
179
180
181
182
183
    template<class X, class Y>
    class Divisible
    {
        typedef boost::numeric::ublas::type_deduction_detail::base_result_of<X, Y> base_type;
        static typename base_type::x_type x;
        static typename base_type::y_type y;
        static const std::size_t size = sizeof (
                   boost::numeric::ublas::type_deduction_detail::test<
                        typename base_type::x_type
                      , typename base_type::y_type
184
                    >(x * y)
185
186
187
188
189
190
191
192
193
                );

        static const std::size_t index = (size / sizeof (char)) - 1;
        typedef typename boost::mpl::at_c<
    	typename base_type::types, index>::type id;
    public:
	/// Result of division
        typedef typename id::type result_type;
    };
194

195
196
197
198
199
200
201
202
#endif


#ifdef __GXX_CONCEPTS__
    concept UnaryStaticFunctor<typename F, typename T>
      : std::Callable1<F, T>
    {
	typename result_type;
203

204
205
206
207
	static result_type F::apply(T);
    };
#else
    /// Concept UnaryFunctor
208
    /** With concept corresponds to std::Callable1 */
209
210
211
212
213
    template <typename T>
    struct UnaryFunctor
    {
	/// Result type of operator()
	typedef associated_type result_type;
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
	/// The unary  function
	result_type operator()(T);
    };


    /// Concept UnaryStaticFunctor
    /**
       \par Refinement of:
       - std::Callable1 < T >
    */
    template <typename T>
    struct UnaryStaticFunctor
      : public UnaryFunctor<T>
    {
	/// Result type of apply
	typedef associated_type result_type;
231

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
	/// The unary static function
	static result_type apply(T);

	/// The application operator behaves like apply. Exists for compatibility with UnaryFunctor
	result_type operator()(T);
    };
#endif


#ifdef __GXX_CONCEPTS__
    auto concept BinaryStaticFunctor<typename F, typename T, typename U>
      : std::Callable2<F, T, U>
    {
	typename result_type;

	static result_type F::apply(T, U);
    };
#else
    /// Concept BinaryFunctor
251
    /** With concept corresponds to std::Callable2 */
252
253
254
255
256
    template <typename T, typename U>
    struct BinaryFunctor
    {
	/// Result type of operator()
	typedef associated_type result_type;
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
	/// The unary  function
	result_type operator()(T, U);
    };

    /// Concept BinaryStaticFunctor
    /**
       \par Refinement of:
       - BinaryFunctor <T, U>
    */
    template <typename T, typename U>
    struct BinaryStaticFunctor
	: public BinaryFunctor <T, U>
    {
	/// Result type of apply
	typedef associated_type result_type;
273

274
275
276
277
278
279
280
281
282
283
284
285
286
	/// The unary static function
	static result_type apply(T, U);

	/// The application operator behaves like apply. Exists for compatibility with BinaryFunctor
	result_type operator()(T, U);
    };
#endif

/*@}*/ // end of group Concepts

} // namespace mtl

#endif // MTL_STD_CONCEPT_INCLUDE