concept/concept_tools.hh

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