00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __LIST_CONCEPT_HH
00019 # define __LIST_CONCEPT_HH
00020
00021 # include "list.hh"
00022
00023 namespace aurelia {
00024 template <typename T>
00025 struct list_model;
00026
00030 template <typename Model>
00031 struct list_concept: public Model {
00032 typedef typename Model::cons_t cons_t;
00033 typedef typename Model::head_t head_t;
00034 typedef typename Model::tail_t tail_t;
00035 enum: unsigned { size = (unsigned)Model::size };
00036 #ifdef DOC_GEN
00037 head head(cons);
00038 tail tail(cons);
00039 cons cons(head, tail);
00040 #else
00041 static_assert(((unsigned)list_model<tail_t>::model::size+1 == size)
00042 || ((size == 0) &&
00043 ((unsigned)list_model<tail_t>::model::size == 0)),
00044 "Wrong size");
00045 static_assert(std::is_same<decltype(head(std::declval<cons_t>())),
00046 head_t>::value,
00047 "head(cons) does not return the right type");
00048 static_assert(std::is_same<decltype(tail(std::declval<cons_t>())),
00049 tail_t>::value,
00050 "tail(cons) does not return the right type");
00051 static_assert(std::is_same<decltype(cons(std::declval<head_t>(),
00052 std::declval<tail_t>())),
00053 cons_t>::value,
00054 "cons(head,tail) does not return the right type");
00055
00056 typedef void check;
00057 #endif
00058 };
00059
00062 template <typename T>
00063 struct list_model {
00064 typedef void no_model;
00065 };
00066
00069 template <typename H, typename T>
00070 struct list_model<list_cons<H, T> > {
00071 struct model {
00072 typedef list_cons<H, T> cons_t;
00073 typedef H head_t;
00074 typedef T tail_t;
00075 enum : unsigned { size = list_cons<H, T>::size };
00076 };
00077 };
00078
00081 template <>
00082 struct list_model<list_nil> {
00083 struct model {
00084 typedef list_nil cons;
00085 typedef void head;
00086 typedef list_nil tail;
00087 enum : unsigned { size = list_nil::size };
00088 };
00089 };
00090
00091 template <template <typename> class Predicate,
00092 typename T,
00093 typename M = typename aurelia::list_model<T>::model,
00094 bool = std::is_same<void, typename M::head_t>::value,
00095 bool = Predicate<typename M::head_t>::value>
00096 struct all_elements: public std::false_type {
00097 };
00098
00099 template <template <typename> class Predicate,
00100 typename T, typename M, bool whatever>
00101 struct all_elements<Predicate, T, M, true, whatever>
00102 : public all_elements<Predicate, typename M::tail_t> {
00103 };
00104
00105 template <template <typename> class Predicate,
00106 typename T, typename M>
00107 struct all_elements<Predicate, T, M, false, true>: public std::true_type {
00108 };
00109
00110 }
00111
00112 #endif