00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef CONCEPT_TOOLS_HH
00018 # define CONCEPT_TOOLS_HH
00019
00020 # include <type_traits>
00021 # include <memory>
00022 # include <cassert>
00023 # include "../wrappers/operators.hh"
00024 # include "parse_ids.hh"
00025
00028
00032 # define ENABLE_IF(X...) \
00033 typename = typename std::enable_if< ::catsfoot::eval< X >::value>::type
00034
00038 # define ENABLE_IF_NOT(X...) \
00039 typename = typename std::enable_if<!::catsfoot::eval< X >::value>::type
00040
00044 # define IF(X...) \
00045 ::catsfoot::eval< X >::value
00046
00048 # define AXIOMS(X...) \
00049 static auto get_axioms() -> \
00050 decltype(::catsfoot::details::zip_vec_tuple \
00051 (::catsfoot::details::split_identifiers(#X), \
00052 std::make_tuple(X))) { \
00053 return ::catsfoot::details::zip_vec_tuple \
00054 (::catsfoot::details::split_identifiers(#X), \
00055 std::make_tuple(X)); \
00056 }
00057
00059
00060 #include "has_requirements.hh"
00061 #include "is_concept.hh"
00062 #include "static_and.hh"
00063
00064 namespace catsfoot {
00067 template <typename T>
00068 struct verified: public std::false_type {
00069 };
00070
00072 template <typename... T>
00073 struct concept_list {};
00074
00075 namespace details {
00077 template <typename T,
00078 bool = has_requirements<T>::value,
00079 bool = is_concept<T>::value,
00080 bool = is_auto_concept<T>::value>
00081 struct eval: public T {
00082 };
00083
00085 template <typename T, bool B>
00086 struct eval<T, true, true, B>:
00087 public static_and<eval<typename T::requirements>,
00088 verified<T> > {
00089 };
00090
00092 template <typename T>
00093 struct eval<T, true, false, true>:
00094 public static_and<eval<typename T::requirements>>
00095 {
00096 };
00097
00099 template <typename... T>
00100 struct eval<concept_list<T...>, false, false, false>:
00101 public static_and<eval<T>... > {
00102 };
00103 }
00104
00107 template <typename T>
00108 struct eval: public details::eval<T> {
00109 };
00110
00111 namespace details {
00113 template <typename T>
00114 struct class_assert_verified {
00115 static_assert(verified<T>::value,
00116 "Concept was not verified");
00117 };
00118
00120 template <typename T,
00121 bool = is_concept<T>::value,
00122 bool = is_auto_concept<T>::value,
00123 bool = has_requirements<T>::value>
00124 struct class_assert_concept {
00125 static_assert(T::value, "Missing requirement");
00126 };
00127
00129 template <typename F, typename... T, bool A, bool B, bool C>
00130 struct class_assert_concept<concept_list<F, T...>, A, B, C>:
00131 public virtual class_assert_concept<F>,
00132 public virtual class_assert_concept<concept_list<T...> > {
00133 };
00134
00136 template <bool A, bool B, bool C>
00137 struct class_assert_concept<concept_list<>, A, B, C> {
00138 };
00139
00141 template <typename T, bool B>
00142 struct class_assert_concept<T, true, B, true>:
00143 public virtual class_assert_concept<typename T::requirements>,
00144 public virtual class_assert_verified<T> {
00145 };
00146
00148 template <typename T>
00149 struct class_assert_concept<T, false, true, true>:
00150 public class_assert_concept<typename T::requirements> {
00151 };
00152
00153 }
00154
00167 template <typename T>
00168 struct class_assert_concept:
00169 public details::class_assert_concept<T> {
00170 };
00171
00172
00177 template <typename T>
00178 void assert_concept(const T&) {
00179 class_assert_concept<T>();
00180 }
00181
00182 }
00183
00184 #endif