concept/product.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 PRODUCT_HH
00018 # define PRODUCT_HH
00019 
00020 # include "concept_tools.hh"
00021 # include "../axioms/axioms.hh"
00022 # include "../utils/call_tuple.hh"
00023 # include "../utils/call_with.hh"
00024 # include "../wrappers/function_wrappers.hh"
00025 # include "../type_traits/is_callable.hh"
00026 # include "congruence.hh"
00027 
00028 namespace catsfoot {
00029 
00030   template <typename Type,
00031             typename Constructor,
00032             typename... Projections>
00033   struct product: public concept {
00034     typedef concept_list<
00035       is_callable<Projections(const Type&)>...,
00036       is_callable
00037       <Constructor(typename is_callable<Projections(const Type&)>
00038                    ::result_type...)>,
00039       std::is_convertible
00040       <typename is_callable
00041        <Constructor(typename is_callable
00042                     <Projections(const Type&)>::result_type...)>::result_type,
00043        Type>,
00044       equivalence_eq<Type>,
00045       equivalence_eq
00046       <typename is_callable<Projections(const Type&)>::result_type>...
00047       > requirements;
00048 
00049     static void projections(const std::tuple
00050                             <typename is_callable<Projections(const Type&)>
00051                              ::result_type...>& comps,
00052                             const std::tuple<Projections...>& p,
00053                             const Constructor& constr) {
00054       axiom_assert(call_tuple(p, call_with(constr, comps)) == comps);
00055     }
00056 
00057     static void universality(const Type& t,
00058                              const std::tuple<Projections...>& p,
00059                              const Constructor& constr) {
00060       axiom_assert(call_with(constr, call_tuple(p, t)) == t);
00061     }
00062 
00063     AXIOMS(projections, universality);
00064   };
00065 
00066   template <typename Type,
00067             typename... Projections>
00068   struct simple_product: public concept {
00069     typedef concept_list<
00070       is_constructible
00071       <Type(typename is_callable<Projections(const Type&)>::result_type...)>,
00072       product<Type, constructor_wrap<Type>,
00073               Projections...>
00074       > requirements;
00075   };
00076 
00077   template <typename Type, typename... Projections>
00078   struct verified<product
00079                   <Type,
00080                    constructor_wrap
00081                    <Type>, Projections...> >:
00082     public verified<simple_product<Type, Projections...> > {};
00083 
00084 }
00085 
00086 #endif