concept.hpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2014, 2015 Ableton AG, Berlin. All rights reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21 //
22 
51 #pragma once
52 
54 #include <atria/meta/utils.hpp>
55 #include <atria/meta/pack.hpp>
56 
57 #include <ableton/build_system/Warnings.hpp>
58 ABL_DISABLE_WARNINGS
59 #include <boost/mpl/eval_if.hpp>
60 #include <boost/mpl/apply.hpp>
61 ABL_RESTORE_WARNINGS
62 #include <algorithm>
63 
64 namespace atria {
65 namespace meta {
66 
70 constexpr bool all()
71 {
72  return true;
73 }
74 
75 template <typename T, typename ...Ts>
76 constexpr bool all(T x, Ts ...xs)
77 {
78  return x && all(xs...);
79 }
80 
86 template <typename ...Ts>
87 constexpr bool valid()
88 {
89  return true;
90 }
91 
109 template <bool Requirement>
111 
117 template <typename ...Ts>
118 void expressions(Ts&&...);
119 
151 template <typename ConceptSig, typename Enable=void>
152 struct models
153  : std::false_type {};
154 
155 template <typename ConceptSpecT, typename ...Ts>
156 struct models<
157  ConceptSpecT(Ts...),
158  estd::void_t<
159  decltype(std::declval<ConceptSpecT>().requires_(
160  std::declval<Ts>()...))
161  >
162  >
163  : std::true_type
164 {};
165 
166 template <typename ConceptSpecT, typename T>
167 struct models_ : models<ConceptSpecT(T)> {};
168 
175 template<typename ConceptSig>
176 constexpr bool check()
177 {
178  return check(pack<ConceptSig>{});
179 }
180 
181 template<typename ConceptSpecT, typename ...Ts>
182 constexpr bool check(pack<ConceptSpecT(Ts...)>)
183 {
184  return valid<decltype(
185  std::declval<ConceptSpecT>().requires_(
186  std::declval<Ts>()...))>();
187 }
188 
189 template<template<typename...>class ConceptSpecT, typename ...Ts>
190 constexpr bool check(pack<ConceptSpecT<Ts...> >)
191 {
192  return valid<decltype(
193  std::declval<ConceptSpecT<Ts...> >().requires_(
194  std::declval<Ts>()...))>();
195 }
196 
211 #define ABL_CONCEPT constexpr
212 
243 #define ABL_CONCEPT_SPEC(concept_name) \
244  struct concept_name ## _spec; \
245  template <typename... Ts> \
246  ABL_CONCEPT bool concept_name() \
247  { \
248  return ::atria::meta::models<concept_name ## _spec (Ts...)>(); \
249  } \
250  struct concept_name ## _spec
251 
252 
259 template <typename T, typename ...Mfs>
260 struct if_any;
261 
262 template <typename T, typename Mf, typename ...Mfs>
263 struct if_any<T, Mf, Mfs...> : boost::mpl::eval_if<
264  typename boost::mpl::apply1<Mf, T>::type,
265  std::true_type,
266  if_any<T, Mfs...>
267  >
268 {
269 };
270 
271 template <typename T, typename Mf>
272 struct if_any<T, Mf> {
273  using type = typename boost::mpl::apply1<Mf, T>::type;
274 };
275 
279 template <typename T, typename... Mfs>
281  if_any<T, Mfs...>::type::value,
282  int>;
283 
284 
290 #define ABL_ASSERT_CONCEPT(concept, ...) \
291  static_assert( \
292  concept<__VA_ARGS__>(), \
293  "Concept: " #concept \
294  " must be satisfied by types: " #__VA_ARGS__) \
295 
296 
301 #define ABL_ASSERT_NOT_CONCEPT(concept, ...) \
302  static_assert( \
303  !concept<__VA_ARGS__>(), \
304  "Concept: " #concept \
305  " must not be satisfied by types: " #__VA_ARGS__) \
306 
307 
308 } // namespace meta
309 } // namespace atria
typename detail::make_void< Ts... >::type void_t
Similar to C++17 std::void_t.
Definition: type_traits.hpp:48
constexpr bool check()
Like models, but fails at compile-time when the specification is not met.
Definition: concept.hpp:176
constexpr bool valid()
Concept that is always satisfied by the type or family of types that is passed to it...
Definition: concept.hpp:87
typename std::enable_if< X, T >::type enable_if_t
Similar to C++14 std::enable_if_t.
Definition: type_traits.hpp:84
estd::enable_if_t< Requirement, int > require
Utility to define concepts in terms of other concepts or other kinds boolean requirements.
Definition: concept.hpp:110
estd::enable_if_t< if_any< T, Mfs... >::type::value, int > require_any
Like require, but based on the semantics of if_any.
Definition: concept.hpp:282
constexpr bool all()
Returns true if all the passed in values are true.
Definition: concept.hpp:70
MPL-compatible sequence that just holds a vector of types as a paremeter pack.
Definition: pack.hpp:57
Metafunction that given a type T and a one or more of MPL metafunction classes Mfs that boolean metaf...
Definition: concept.hpp:260
void expressions(Ts &&...)
Allows to validate a sequence of expressions in a single decltype.
Returns whether a concept signature ConceptSig is satisfied.
Definition: concept.hpp:152
C++ amazing templates and reusable implementations awesomeness.
Definition: _doc.hpp:35
Fork me on GitHub