Du Suchst Übung!?
-
So, fertig! Ich frag mal gar nicht sondern Poste:
#include <array> typedef uint_least64_t fac_result_t; typedef uint8_t fac_of_t; fac_of_t constexpr N = 20; typedef std::array<fac_result_t, N> array_t; constexpr fac_result_t fak(fac_of_t n) { return n > 1 ? fak(n-1)*n : 1; } /// *** Hier wird es interessant: template<fac_of_t still, fac_result_t F(fac_of_t), fac_of_t ... args> struct table_impl { static array_t constexpr table = table_impl<still - 1, F, args..., N - still>::table; }; template<fac_of_t ... args, fac_result_t F(fac_of_t)> struct table_impl<0, F, args...> { static array_t constexpr table { F(args)... }; }; /// *** array_t constexpr table = table_impl<N, fak>::table; #include <cassert> int main() { for (unsigned i=0; i<N; ++i) assert(table[i] == fak(i)); }Die Lösung ist bereits eingereicht

-
Verbesserungsvorschlag: Verzichte auf die explizite Rekursion unter Benutzung von campers make_index_list.
-
Meine Lösung zu all_equal
template <typename... Ts> struct all_equal; template <typename T, typename... Ts> struct all_equal<T, Ts...> : std::is_same<tmpalg::type_list<T, Ts...>, tmpalg::type_list<Ts..., T>> {}; template <> struct all_equal<> : std::true_type {};(nicht ganz das Geforderte).
Edit: Wenn ich recht darüber nachdenke, kann man so dann auch all_of&co schreiben:
template <typename TL, template <typename> class Pred> struct all_of; template <typename... T, template <typename> class Pred> struct all_of<type_list<T...>> : all_equal<std::true_type, std::integral_constant<bool, Pred<T>::value>...> {}; template <typename TL, template <typename> class Pred> struct none_of; template <typename... T, template <typename> class Pred> struct none_of<type_list<T...>> : all_equal<std::false_type, std::integral_constant<bool, Pred<T>::value>...> {}; template <typename TL, template <typename> class Pred> struct any_of : std::integral_constant<bool, !none_of<TL, Pred>::value> {};mit minimalem Instantiierungsaufwand.
-
template <typename... Ts> struct all_equal; template <typename T, typename... Ts> struct all_equal<T, Ts...> : std::is_same<tmpalg::type_list<T, Ts...>, tmpalg::type_list<Ts..., T>> {}; template <> struct all_equal<> : std::true_type {};
Das ist genial!
-
Camper, hast du auch eine Lösung für #40 ohne merge&co & explizite Rekursion?
template <typename... T> struct type_list { typedef type_list type; }; template <typename T> struct identity_ { typedef T type; }; template <template<typename>class A, typename TL> struct transform_32; template <template<typename>class A, typename... T> struct transform_32<A, type_list<T...> > : type_list<typename A<T>::type...> {}; template <typename TL> struct head; template <typename T, typename... Ts> struct head<type_list<T, Ts...> > : identity_<T> {}; template <typename TL> struct tail; template <typename T, typename... Ts> struct tail<type_list<T, Ts...> > : identity_<type_list<Ts...> > {}; template <template <typename...> class F, typename TL> struct call; template <template <typename...> class F, typename... Ts> struct call<F, type_list<Ts...> > : identity_<typename F<Ts...>::type> {}; template <typename T, typename TL> struct cons; template <typename T, typename... Ts> struct cons<T, type_list<Ts...> > : identity_<type_list<T, Ts...> > {}; template <template <typename...> class F, typename... TLs> struct transform_; template <template <typename...> class F, typename... TLs> using transform = typename transform_<F, TLs...>::type; template <template <typename...> class F, typename... TLs> struct transform_<F, type_list<>, TLs...> : identity_<type_list<> > {}; template <template <typename...> class F> struct transform_<F> : identity_<type_list<> > {}; template <template <typename...> class F, typename TL> struct call_transform { template <typename... TLs> using trans = transform<F, TLs...>; using type = typename call<trans, TL>::type; }; template <template <typename...> class F, typename... TLs> struct transform_ : identity_<typename cons<typename call<F, typename transform_32<head, type_list<TLs...> >::type>::type, typename call_transform<F, typename transform_32<tail, type_list<TLs...> >::type>::type>::type > {};
-
Ich habe mir bisher nicht die Mühe gemacht, selbst eine Lösung zu erstellen.
Eine Merge ohne Rekursion ist allerdings möglich, wenn man at etwas verallgemeinert...
Ich schreibs mal auf, wenn Sone seine Lösung abgeliefert hat.
-
Ich schreibs mal auf, wenn Sone seine Lösung abgeliefert hat.
Sone hat Fragen zur Aufgabe.
Und zwar, nach welchen Kriterien soll entschieden werden ob alle Elemente einer Typliste zu einem neuen Element der neuen TL verschmelzen, oder ob jedes Element jeder Typliste zur neuen Typliste dazuzählt?
-
Verstehe die Frage nicht. Hast du ein Beispiel?
-
Unter Benutzung von Campers
make_index_listund den Helfernat,sizeundidentity_aus #32:template <template <typename...> class F, typename TL> struct call; template <template <typename...> class F, typename... Ts> struct call<F, type_list<Ts...> > : identity_<typename F<Ts...>::type> {}; template <template <typename...> class F, typename I, typename... TLs> struct transform_; template <template <typename...> class F, typename... TLs> using transform = typename transform_<F, make_index_list<size<at<type_list<TLs...>, 0> >::value>, TLs...>::type; template <template <typename...> class F, int... I, typename... TLs> struct transform_<F, index_list<I...>, TLs...> { template <int i> struct tlat : identity_<type_list<at<TLs, i>...> > {}; using type = type_list<typename call<F, typename tlat<I>::type>::type...>; };(Mich wundert, dass wenn man Zeile 11 durch
template <int i> using tlat = identity_<type_list<at<TLs, i>...> >;ersetzt, sowohl GCC als auch Clang den Code ablehnen, weil sie Pack Expansion über beide Template Parameter zu machen versuchen.)
-
g++ kommt bei mir mit dem Code gar nicht zurecht
$ LC_MESSAGES=en_US.utf8 g++-4.8.0-alpha20121216 -std=c++11 test.cpp -Wno-non-template-friend test.cpp: In substitution of ‘template<template<class ...> class F, class ... TLs> using transform = typename tmpalg::transform_<F, typename tmpalg::make_index_list_<typename tmpalg::size_<typename tmpalg::at_<tmpalg::type_list<Ts ...>, 0ul>::type>::type:: value, tmpalg::index_list<> >::type, TLs ...>::type [with F = std::add_pointer; TLs = {tmpalg::type_list<int, char, double>}]’: test.cpp:79:62: required from here test.cpp:67:112: error: invalid use of incomplete type ‘struct tmpalg::transform_<std::add_pointer, tmpalg::index_list<0ul, 1ul, 2ul>, tmpalg::type_list<int, char, double> >’ using transform = typename transform_<F, make_index_list<size<at<type_list<TLs...>, 0> >::value>, TLs...>::type; ^ test.cpp:65:8: error: declaration of ‘struct tmpalg::transform_<std::add_pointer, tmpalg::index_list<0ul, 1ul, 2ul>, tmpalg::type_list<int, char, double> >’ struct transform_; ^ test.cpp:79:95: error: template argument 1 is invalid static_assert( std::is_same<transform<std::add_pointer, list1>, type_list<int*, char*, double*>>::value, "transform failed!" );g++ 4.7.2 ist analog. clang macht dagegen keine Probleme, auch nicht mit
template <int i> using tlat = identity_<type_list<at<TLs, i>...> >;$ LC_MESSAGES=en_US.utf8 g++-4.7.2 --version g++-4.7.2 (Gentoo 4.7.2 p1.3, pie-0.5.5) 4.7.2 $ LC_MESSAGES=en_US.utf8 g++-4.8.0-alpha20121216 --version g++-4.8.0-alpha20121216 (Gentoo 4.8.0_alpha20121216) 4.8.0-alpha20121216 20121216 (experimental) $ LC_MESSAGES=en_US.utf8 clang++ --version clang version 3.2 (tags/RELEASE_32/final)evtl. ist deine Version veraltet?
-
Naja, der gepostete Code kompiliert bei mir mit g++ und clang++.
% clang++ --version Debian clang version 3.1-8 (branches/release_31) (based on LLVM 3.1) Target: i386-pc-linux-gnu Thread model: posix % g++ --version g++ (Debian 4.7.2-5) 4.7.2 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.Keine Ahnung, wie aktuell die sind, ich nehme einfach die aus den Paketquellen und warte bis sie sich von selber aktualisieren.
-
mit clang-3.2 läuft auch dieser Code
Es gibt noch ein paar Bugs in g++, wenn Aliastemplates als Templateparemeter eingesetzt werden.
-
Stimmt. Das ist nett, weil jetzt kann man ihn verkürzen (und clang kompiliert ihn immer noch).
template <int i> using tlat = type_list<at<TLs, i>...>; using type = type_list<typename call<F, tlat<I> >::type...>;
-
Das dürfte ziemlich optimal sein.
EIn hübscher Test ist auch
template <typename... T> struct type_list : identity_<type_list<T...>> {}; template <typename... TLs> using transpose = transform<type_list, TLs...>; static_assert( std::is_same<transpose<list1, list2>, type_list<type_list<int, long>, type_list<char, short>, type_list<double, float>>>::value, "transform failed!" );Jetzt fehlt noch eine Aufgabe für fold (wobei ich bezweifle, dass sich dabei etwas Eleganteres als 08/15-Rekursion finden lässt), dann dürfte die die elementaren Funktionen vollständig sein.
-
Fold wäre wirklich ganz nett, nicht um sich selber willen, sondern für andere Algorithmen:
template <int S, typename I, typename TL> struct reverse_; template <typename TL> using reverse = typename reverse_<size<TL>::value, make_index_list<size<TL>::value>, TL>::type; template <int S, int... I, typename TL> struct reverse_<S, index_list<I...>, TL> : identity_<type_list<at<TL, S - I - 1>...> > {};würde dann zu
template <template <typename...> class F, typename TL> using reverse = fold<cons, type_list<>, TL>;