dataset/tuple_generator.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 __TUPLE_GENERATOR_HH
00018 # define __TUPLE_GENERATOR_HH
00019 
00020 # include <tuple>
00021 
00022 namespace catsfoot {
00023 
00024   namespace details {
00025 
00026     template <typename U>
00027     struct tuple_generator_tool {};
00028 
00030     template <typename... U>
00031     struct tuple_generator_tool<std::tuple<U...>& >:
00032     public tuple_generator_tool<std::tuple<U...> > {
00033     };
00034 
00036     template <typename... U>
00037     struct tuple_generator_tool<const std::tuple<U...>& >:
00038     public tuple_generator_tool<std::tuple<U...> > {
00039     };
00040 
00042     template <typename... U>
00043     struct tuple_generator_tool<std::tuple<U...> > {
00044 
00045       template <typename... V, typename... Values,
00046                 typename = void,
00047                 typename = typename std::enable_if
00048                 <(sizeof...(V) == sizeof...(Values))>::type>
00049       std::list<std::tuple<U...> >
00050       make_list(std::tuple<V...>&, Values... values...)
00051       const {
00052         return std::list<std::tuple<U...> >
00053           {std::tuple<U...>
00054             {std::forward<Values>(values)...}};
00055       }
00056 
00057       template <typename... V, typename... Values,
00058                 typename = typename
00059                 std::enable_if<(sizeof...(V) > sizeof...(Values))>::type>
00060       std::list<std::tuple<U...> >
00061       make_list(std::tuple<V...>& containers,
00062                 Values... values) const
00063       {
00064         std::list<std::tuple<U...> > ret;
00065         typename std::tuple_element<sizeof...(Values),
00066                                     std::tuple<V...> >::type&
00067         local_container(std::get<sizeof...(Values)>(containers));
00068 
00069         for (auto i = local_container.begin();
00070              i != local_container.end();
00071              ++i) {
00072           auto r = make_list(containers, std::forward<Values>(values)...,
00073                              typename
00074                              std::tuple_element<sizeof...(Values),
00075                                                 std::tuple<U...> >::type(*i));
00076           ret.splice(ret.end(), r);
00077         }
00078         return ret;
00079       }
00080 
00081       template <typename Generator>
00082       std::list<std::tuple<U...> >
00083       operator()(Generator& g) const {
00084         std::tuple<typename std::decay
00085                    <decltype(g.get(selector<U>()))>::type
00086                    ...>
00087           containers(g.get(selector<U>())...);
00088         return make_list(containers);
00089       }
00090     };
00091 
00093     template <typename Generator>
00094     struct tuple_generator {
00095     private:
00096       Generator g;
00097 
00098     public:
00099       tuple_generator(Generator&& g): g(std::move(g)) {}
00100       tuple_generator(const Generator& g): g(g) {}
00101 
00102       tuple_generator(const tuple_generator& other): g(other.g) {}
00103       tuple_generator(tuple_generator&& other): g(std::move(other.g)) {}
00104 
00105       template <typename U>
00106       decltype(tuple_generator_tool<U>()
00107                (std::declval<const Generator&>()))
00108       get(selector<U>) {
00109         return tuple_generator_tool<U>()(g);
00110       }
00111     };
00112   }
00113 
00116   template <typename Generator>
00117   details::tuple_generator<typename std::decay<Generator>::type>
00118   tuple_gen(Generator&& g) {
00119     return details::tuple_generator<typename std::decay<Generator>::type>
00120       (std::forward<Generator>(g));
00121   }
00122 }
00123 
00124 #endif