list_concept.hh

00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
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