2016-04-10 16 views
0

typename FindPacksToMerge<P<Packs...>, P<Ts...>>::type ist P<As...> so dass As... ist eine Sequenz von Packs von Packs... (ggf. mit repeats) undeine Reihe von Packungen zu finden, um eine gegebene Packung

std::is_same< typename concat<As...>::type, P<Ts...> >::value == true 

beispielsweise gleich fusionieren,

std::cout << std::is_same< 
    FindPacksToMerge< P< P<int, char, long>, P<int>, P<double, bool>, P<bool, char, int> >, P<int, bool, char, int, int, double, bool> >::type, 
    P< P<int>, P<bool, char, int>, P<int>, P<double, bool> > 
>::value << '\n'; 

sollte true ausgeben. Vorerst wollen wir uns damit zufrieden geben, eine Antwort zu erhalten, falls es mehrere Antworten gibt.

Ich habe die entsprechenden Helfer structs bereits geschrieben (concat verschmilzt eine beliebige Anzahl von Packungen, split<N, Pack> eine Packung spaltet, so dass der Kopf mit N-Typen und dem Schwanz erhalten werden, pack_size gibt die Anzahl der Arten in der Packung):

template <typename T> struct Identity { using type = T; }; 

template <typename...> struct concat; 

template <template <typename...> class P, typename... Ts, typename... Us> 
struct concat<P<Ts...>, P<Us...>> { 
    using type = P<Ts..., Us...>; 
}; 

template <typename Pack> 
struct concat<Pack> : Identity<Pack> {}; 

template <typename Pack1, typename Pack2, typename... Packs> 
struct concat<Pack1, Pack2, Packs...> { 
    using type = typename concat<Pack1, typename concat<Pack2, Packs...>::type>::type; 
}; 

template <std::size_t N, typename Intput, typename... Output> struct split; 

template <std::size_t N, template <typename...> class P, typename First, typename... Rest, typename... Output> 
struct split<N, P<First, Rest...>, Output...> : split<N-1, P<Rest...>, Output..., First> {}; 

template <template <typename...> class P, typename First, typename... Rest, typename... Output> 
struct split<0, P<First, Rest...>, Output...> { 
    using head = P<Output...>; 
    using tail = P<First, Rest...>; 
}; 

template <template <typename...> class P, typename... Output> 
struct split<0, P<>, Output...> { 
    using head = P<Output...>; 
    using tail = P<>; 
}; 

template <typename Pack> struct pack_size; 

template <template <typename...> class P, typename... Ts> 
struct pack_size<P<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {}; 

Aber das Problem ist die Rekursion. Nehmen wir an, unter den Typen P<Packs...> testen wir den Typ Pack. Wenn split<pack_size<Pack>::value, P<Ts...>>::head mit Pack übereinstimmt, wiederholen Sie die Suche mit split<pack_size<Pack>::value, P<Ts...>>::tail (Starten der Suche in P<Packs...> zurück bei der ersten Packung). Wir speichern alle gefundenen Pakete in einem Ausgabepack auf dem Weg. Wenn wir das Ende von P<Ts...> erreichen und feststellen, dass der verbleibende Schwanz kürzer oder gleich lang ist wie das kürzeste Paket in P<Packs...> und nicht mit einem Paket in P<Packs...> übereinstimmt, ist die Suche in dieser Zeile fehlgeschlagen. Also müssen wir die Suche erneut starten. Aber woher? Von der letzten Packung, die ausprobiert wurde (wir müssen die Packung danach ausprobieren). Und wenn alle Packs danach auch keine Antwort geben, müssen wir wieder einen Schritt zurückgehen, aber wo ist das? Das ist eine Baumdurchquerung, aber wie erinnert man sich daran, dass wir in einer beliebigen Anzahl von Generationen aufgehört haben? Oder vielleicht gibt es insgesamt einen besseren Ansatz? Der Versuch, alle möglichen Kombinationen von P<Packs...> bis zur Übereinstimmung mit P<Ts...> zusammenzuführen, kann möglicherweise keine praktikable Lösung sein.

Dies ist die Template-Spezialisierung, an der ich gerade arbeite, die behoben werden muss. Ich habe das Gefühl, dass die Lösung, die mir entgeht, eine kurze ist.

template <typename PackOfPacks, typename Untried, typename Output, typename Match> struct FindPacksToMergeHelper; 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct FindPacksToMergeHelper<PackOfPacks, P<First, Rest...>, P<Output...>, Match> : std::conditional_t< 
    pack_size<Match>::value < pack_size<First>::value, 
    FindPacksToMergeHelper<PackOfPacks, P<Rest...>, P<Output...>, Match>, // Move on to the next of the untried packs. 
    std::conditional_t< 
     std::is_same<First, Match>::value, 
     Identity<P<Output..., First>>, // Answer found. 
     std::conditional_t< 
      std::is_same<First, typename split<pack_size<First>::value, Match>::head>::value, // Check if the head of Match is the same as First. 
      FindPacksToMergeHelper<PackOfPacks, PackOfPacks, P<Output..., First>, typename split<pack_size<First>::value, Match>::tail>, // Try with the tail now, starting back at the first type in PackOfPacks. 
      FindPacksToMergeHelper<PackOfPacks, P<Rest...>, P<Output...>, Match> // Move on to the next of the untried packs. 
     > 
    > 
> {}; 

Antwort

1

Eine Packung:

template<class... > class pack {}; 

Filter eine durch ein Prädikat von Typen Packung:

template<class, class Pred> struct filter; 

template<class... Ts, class F> 
struct filter<pack<Ts...>, F> 
{ 
    using type = typename concat<std::conditional_t<F::template apply<Ts>::value, 
                pack<Ts>, 
                pack<>>...>::type; 
}; 

Ein Prädikat für "U ein Präfix von T":

template<class T> 
struct is_prefix_of 
{ 
    template<class U, bool = pack_size<T>::value >= pack_size<U>::value> 
    struct apply; 
    template<class U> 
    struct apply<U, true> 
     : std::is_same<U, typename split<pack_size<U>::value, T>::head> { }; 
    template<class U> 
    struct apply<U, false> : std::false_type {}; 
}; 

Tag-Typ zur Anzeige des Fehlers:

struct fail; 

Das Tier:

template<class Packs, class Pack, 
     class Current = typename filter<Packs, is_prefix_of<Pack>>::type> 
struct find_packs_to_merge; 

template<class Packs, class Pack, class First, class... Rest> 
struct find_packs_to_merge<Packs, Pack, pack<First, Rest...>> 
{ 
    // Get the remainder of the pack we still need to work on 
    using Remaining = typename split<pack_size<First>::value, Pack>::tail; 
    // search for the packs needed for the tail 
    using PR = typename find_packs_to_merge<Packs, Remaining>::type; 

    // on failure, try the next pack 
    // on success, concat First to PR and we are done. 
    // Note the short circuiting. 
    using type = typename std::conditional_t<std::is_same<fail, PR>::value, 
            find_packs_to_merge<Packs, Pack, pack<Rest...>>, 
            concat<pack<First>, PR>>::type; 
}; 

template<class Packs, class Pack> 
struct find_packs_to_merge<Packs, Pack, pack<>> 
{ 
    // we tried everything and nothing works. 
    using type = fail; 
}; 

template<class Packs> 
struct find_packs_to_merge<Packs, pack<>, pack<>> 
{ 
    // Success - we've used up the pack. 
    using type = pack<>; 
}; 
0

Ich habe gelesen noch nicht T. C.-Lösung, wie ich mit meiner Methode fort. Der folgende Code gilt für 6 Testfälle, aber ich weiß nicht, ob es für einen möglichen Fall funktioniert.

#include <iostream> 
#include <type_traits> 
#include <utility> 

template <typename T> struct Identity { using type = T; }; 

template <typename...> struct concat; 

template <template <typename...> class P, typename... Ts, typename... Us> 
struct concat<P<Ts...>, P<Us...>> { 
    using type = P<Ts..., Us...>; 
}; 

template <typename Pack> 
struct concat<Pack> : Identity<Pack> {}; 

template <typename Pack1, typename Pack2, typename... Packs> 
struct concat<Pack1, Pack2, Packs...> { 
    using type = typename concat<Pack1, typename concat<Pack2, Packs...>::type>::type; 
}; 

template <std::size_t N, typename Intput, typename... Output> struct split; 

template <std::size_t N, template <typename...> class P, typename First, typename... Rest, typename... Output> 
struct split<N, P<First, Rest...>, Output...> : split<N-1, P<Rest...>, Output..., First> {}; 

template <template <typename...> class P, typename First, typename... Rest, typename... Output> 
struct split<0, P<First, Rest...>, Output...> { 
    using head = P<Output...>; 
    using tail = P<First, Rest...>; 
}; 

template <template <typename...> class P, typename... Output> 
struct split<0, P<>, Output...> { 
    using head = P<Output...>; 
    using tail = P<>; 
}; 

template <typename Pack> struct pack_size; 

template <template <typename...> class P, typename... Ts> 
struct pack_size<P<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {}; 

struct Failed; 

template <typename PackOfPacks, typename Untried, typename Output, typename Match> struct FindPacksToMergeImpl; 
template <typename PackOfPacks, typename Untried, typename Output, typename Match, typename Result> struct Check; 
template <typename PackOfPacks, typename Untried, typename Output, typename Match> struct FindPacksToMergeHelper; 
template <typename PackOfPacks, typename Untried, typename Output, typename Match, bool> struct CheckIfPackTooBig; 
template <typename PackOfPacks, typename Untried, typename Output, typename Match, bool> struct CheckIfAnswerFound; 
template <typename PackOfPacks, typename Untried, typename Output, typename Match, bool> struct CheckHead; 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfPackTooBig<PackOfPacks, P<First, Rest...>, P<Output...>, Match, true> : 
    FindPacksToMergeImpl<PackOfPacks, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfPackTooBig<PackOfPacks, P<First, Rest...>, P<Output...>, Match, false> : 
    CheckIfAnswerFound<PackOfPacks, P<First, Rest...>, P<Output...>, Match, std::is_same<First, Match>::value> {}; 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfAnswerFound<PackOfPacks, P<First, Rest...>, P<Output...>, Match, true> : Identity<P<Output..., First>> {}; // We are done. 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfAnswerFound<PackOfPacks, P<First, Rest...>, P<Output...>, Match, false> : 
    CheckHead<PackOfPacks, P<First, Rest...>, P<Output...>, Match, std::is_same<First, typename split<pack_size<First>::value, Match>::head>::value> {}; // Check if the head of Match is the same as First. 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckHead<PackOfPacks, P<First, Rest...>, P<Output...>, Match, true> : 
    FindPacksToMergeImpl<PackOfPacks, PackOfPacks, P<Output..., First>, typename split<pack_size<First>::value, Match>::tail> {}; // Try with the tail now, starting back at the first type in PackOfPacks. 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckHead<PackOfPacks, P<First, Rest...>, P<Output...>, Match, false> : 
    FindPacksToMergeImpl<PackOfPacks, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct FindPacksToMergeHelper<PackOfPacks, P<First, Rest...>, P<Output...>, Match> : 
    CheckIfPackTooBig<PackOfPacks, P<First, Rest...>, P<Output...>, Match, pack_size<Match>::value < pack_size<First>::value> {}; 

template <typename PackOfPacks, template <typename...> class P, typename... Output, typename Match> 
struct FindPacksToMergeHelper<PackOfPacks, P<>, P<Output...>, Match> : Identity<Failed> {}; 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match, typename Result> 
struct Check<PackOfPacks, P<First, Rest...>, P<Output...>, Match, Result> : Identity<Result> {}; // We are done. 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct Check<PackOfPacks, P<First, Rest...>, P<Output...>, Match, Failed> : 
    FindPacksToMergeImpl<PackOfPacks, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. 

template <typename PackOfPacks, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct FindPacksToMergeImpl<PackOfPacks, P<First, Rest...>, P<Output...>, Match> : 
    Check<PackOfPacks, P<First, Rest...>, P<Output...>, Match, typename FindPacksToMergeHelper<PackOfPacks, P<First, Rest...>, P<Output...>, Match>::type> {}; 

template <typename PackOfPacks, template <typename...> class P, typename... Output, typename Match> 
struct FindPacksToMergeImpl<PackOfPacks, P<>, P<Output...>, Match> : Identity<Failed> {}; // This should never be reached, but is needed to compile (it was really hard to check why though). 

template <typename> struct EmptyPack; 

template <template <typename...> class P, typename... Ts> 
struct EmptyPack<P<Ts...>> { using type = P<>; }; 

template <typename PackOfPacks, typename Match> 
using FindPacksToMerge = typename FindPacksToMergeImpl<PackOfPacks, PackOfPacks, typename EmptyPack<PackOfPacks>::type, Match>::type; 

// Testing 
template <typename...> struct P; 

int main() { 
    std::cout << std::boolalpha << std::is_same< 
     FindPacksToMerge< P<P<int, char, long>, P<int>, P<double, bool>, P<bool, char, int>>, P<bool, char, int> >, 
     P< P<bool, char, int> > 
    >::value << '\n'; // true 

    std::cout << std::is_same< 
     FindPacksToMerge< P<P<int, char, long>, P<int>, P<double, bool>, P<bool, char, int>>, P<bool, char, int, bool, char, int> >, 
     P< P<bool, char, int>, P<bool, char, int> > 
    >::value << '\n'; // true 

    std::cout << std::is_same< 
     FindPacksToMerge< P<P<int, char, long>, P<int>, P<double, bool>, P<bool, char, int>>, P<bool, char, int, double, bool> >, 
     P< P<bool, char, int>, P<double, bool> > 
    >::value << '\n'; // true 

    std::cout << std::is_same< 
     FindPacksToMerge< P< P<int, char, long>, P<int>, P<double, bool>, P<bool, char, int> >, P<int, bool, char, int, int, double, bool> >, 
     P< P<int>, P<bool, char, int>, P<int>, P<double, bool> > 
    >::value << '\n'; // true 

    std::cout << std::is_same< 
     FindPacksToMerge< P< P<int, bool>, P<int, char, long>, P<int>, P<double, bool>, P<bool, char, int> >, P<int, bool, char, int, int, double, bool> >, 
     P< P<int>, P<bool, char, int>, P<int>, P<double, bool> > 
    >::value << '\n'; // true (this works even though P<int, bool> is tried (and fails) before P<int> is tried) 

    std::cout << std::is_same< 
     FindPacksToMerge< P< P<int, bool>, P<int, char, long>, P<bool>, P<int>, P<double, bool>, P<bool, char, int> >, P<int, bool, char, int, int, double, bool> >, 
     P< P<int>, P<bool, char, int>, P<int>, P<double, bool> > 
    >::value << '\n'; // true (this works even though after P<int> is correctly tried (after P<int, bool> is tried and failed), then P<bool> is tried (and fails) before P<bool, char, int> is tried) 
} 

Ich werde jetzt an T.C. Ideen arbeiten.

Für diejenigen, die sich fragen, hier ist eine Anwendung von FindTypesToMerge, die diese motiviert:

#include <iostream> 
#include <tuple> 
#include <vector> 
#include <type_traits> 
#include <utility> 

template <typename T> struct Identity { using type = T; }; 

template <typename...> struct concat; 

template <template <typename...> class P, typename... Ts, typename... Us> 
struct concat<P<Ts...>, P<Us...>> { 
    using type = P<Ts..., Us...>; 
}; 

template <typename Pack> 
struct concat<Pack> : Identity<Pack> {}; 

template <typename Pack1, typename Pack2, typename... Packs> 
struct concat<Pack1, Pack2, Packs...> { 
    using type = typename concat<Pack1, typename concat<Pack2, Packs...>::type>::type; 
}; 

template <std::size_t N, typename Intput, typename... Output> struct split; 

template <std::size_t N, template <typename...> class P, typename First, typename... Rest, typename... Output> 
struct split<N, P<First, Rest...>, Output...> : split<N-1, P<Rest...>, Output..., First> {}; 

template <template <typename...> class P, typename First, typename... Rest, typename... Output> 
struct split<0, P<First, Rest...>, Output...> { 
    using head = P<Output...>; 
    using tail = P<First, Rest...>; 
}; 

template <template <typename...> class P, typename... Output> 
struct split<0, P<>, Output...> { 
    using head = P<Output...>; 
    using tail = P<>; 
}; 

template <typename Pack> struct pack_size; 

template <template <typename...> class P, typename... Ts> 
struct pack_size<P<Ts...>> : std::integral_constant<std::size_t, sizeof...(Ts)> {}; 

struct Failed; 

template <typename Pack, typename Untried, typename Output, typename Match> struct FindPacksToMergeImpl; 
template <typename Pack, typename Untried, typename Output, typename Match, typename Result> struct Check; 
template <typename Pack, typename Untried, typename Output, typename Match> struct FindPacksToMergeHelper; 
template <typename Pack, typename Untried, typename Output, typename Match, bool> struct CheckIfPackTooBig; 
template <typename Pack, typename Untried, typename Output, typename Match, bool> struct CheckIfAnswerFound; 
template <typename Pack, typename Untried, typename Output, typename Match, bool> struct CheckHead; 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfPackTooBig<Pack, P<First, Rest...>, P<Output...>, Match, true> : 
    FindPacksToMergeImpl<Pack, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfPackTooBig<Pack, P<First, Rest...>, P<Output...>, Match, false> : 
    CheckIfAnswerFound<Pack, P<First, Rest...>, P<Output...>, Match, std::is_same<typename First::argument_type, Match>::value> {}; 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfAnswerFound<Pack, P<First, Rest...>, P<Output...>, Match, true> : Identity<P<Output..., First>> {}; // We are done. 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckIfAnswerFound<Pack, P<First, Rest...>, P<Output...>, Match, false> : 
    CheckHead<Pack, P<First, Rest...>, P<Output...>, Match, std::is_same<typename First::argument_type, typename split<pack_size<typename First::argument_type>::value, Match>::head>::value> {}; // Check if the head of Match is the same as First::argument_type. 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckHead<Pack, P<First, Rest...>, P<Output...>, Match, true> : 
    FindPacksToMergeImpl<Pack, Pack, P<Output..., First>, typename split<pack_size<typename First::argument_type>::value, Match>::tail> {}; // Try with the tail now, starting back at the first type in Pack. 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct CheckHead<Pack, P<First, Rest...>, P<Output...>, Match, false> : 
    FindPacksToMergeImpl<Pack, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct FindPacksToMergeHelper<Pack, P<First, Rest...>, P<Output...>, Match> : 
    CheckIfPackTooBig<Pack, P<First, Rest...>, P<Output...>, Match, pack_size<Match>::value < pack_size<typename First::argument_type>::value> {}; 

template <typename Pack, template <typename...> class P, typename... Output, typename Match> 
struct FindPacksToMergeHelper<Pack, P<>, P<Output...>, Match> : Identity<Failed> {}; 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match, typename Result> 
struct Check<Pack, P<First, Rest...>, P<Output...>, Match, Result> : Identity<Result> {}; // We are done. 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct Check<Pack, P<First, Rest...>, P<Output...>, Match, Failed> : 
    FindPacksToMergeImpl<Pack, P<Rest...>, P<Output...>, Match> {}; // Move on to the next of the untried packs. 

template <typename Pack, template <typename...> class P, typename First, typename... Rest, typename... Output, typename Match> 
struct FindPacksToMergeImpl<Pack, P<First, Rest...>, P<Output...>, Match> : 
    Check<Pack, P<First, Rest...>, P<Output...>, Match, typename FindPacksToMergeHelper<Pack, P<First, Rest...>, P<Output...>, Match>::type> {}; 

template <typename Pack, template <typename...> class P, typename... Output, typename Match> 
struct FindPacksToMergeImpl<Pack, P<>, P<Output...>, Match> : Identity<Failed> {}; // This should never be reached, but is needed to compile (it was really hard to check why though). 

template <typename> struct EmptyPack; 

template <template <typename...> class P, typename... Ts> 
struct EmptyPack<P<Ts...>> { using type = P<>; }; 

template <typename Pack, typename Match> 
using FindPacksToMerge = typename FindPacksToMergeImpl<Pack, Pack, typename EmptyPack<Pack>::type, Match>::type; 

template <typename... Ts> 
class Storage { 
    std::tuple<std::vector<Ts*>...> inventory; 
    template <typename> struct AddDifferentTypes; 
public: 
    template <typename... Args> 
    void addDifferentTypes (Args&&... args) { 
     using TypesTuple = FindPacksToMerge<std::tuple<Ts...>, std::tuple<Args...>>; // FindPacksToMerge adapted from the FindPacksToMerge.cpp program. 
     AddDifferentTypes<TypesTuple>::execute(this, std::forward<Args>(args)...); 
    } 

    template <typename T> 
    const std::vector<T*>& get() const {return std::get<std::vector<T*>>(inventory);} 
private: 
    template <typename T, typename... Args> 
    void addItem (Args&&... args) { 
     std::get<std::vector<T*>>(inventory).emplace_back(new T{std::forward<Args>(args)...}); 
    } 
}; 

template <typename... Ts> 
template <template <typename...> class P, typename... Vs> 
struct Storage<Ts...>::AddDifferentTypes<P<Vs...>> { 
    template <typename... Args> 
    static void execute (Storage<Ts...>* storage, Args&&... args) { 
     executeHelper<0, 0, P<Vs...>, std::tuple_size<typename Vs::argument_type>::value...>(storage, std::tie(args...)); 
    } 
private: 
    template <std::size_t N, std::size_t Offset, typename TypesTuple, std::size_t First, std::size_t... Rest, typename ArgsTuple> 
    static void executeHelper (Storage<Ts...>* storage, const ArgsTuple& tuple) { 
     add<N, Offset, TypesTuple>(storage, tuple, std::make_index_sequence<First>{}); 
     executeHelper<N + 1, Offset + First, TypesTuple, Rest...>(storage, tuple); 
    } 

    template <std::size_t N, std::size_t Offset, typename TypesTuple, typename ArgsTuple> 
    static void executeHelper (Storage<Ts...>*, const ArgsTuple&) {} // End of recursion. 

    template <std::size_t N, std::size_t Offset, typename TypesTuple, typename ArgsTuple, std::size_t... Is> 
    static void add (Storage<Ts...>* storage, const ArgsTuple& tuple, std::index_sequence<Is...>) { 
     storage->template addItem<std::tuple_element_t<N, TypesTuple>>(std::get<Offset + Is>(tuple)...); 
    } 
}; 

// Testing 
struct Object { 
    int a; 
    bool b; 
    char c; 
    double d; 
    using argument_type = std::tuple<int, bool, char, double>; 
}; 

struct Thing { 
    int a, b; 
    char c; 
    using argument_type = std::tuple<int, int, char>; 
}; 

struct Number { 
    int num; 
    using argument_type = std::tuple<int>; 
}; 

struct SemiObject { 
    int a; 
    bool b; 
    char c; 
    using argument_type = std::tuple<int, bool, char>; 
}; 

int main() { 
    Storage<Number, SemiObject, Object, Thing> storage; 
    storage.addDifferentTypes (1,true,'a',3.5, 1,2,'t', 5,6,'p', 3,false,'b',1.8, 3,true,'t', 8, 3, 4,5,'s'); // Object, Thing, Thing, Object, SemiObject, Number, Number, Thing 

    std::cout << "Objects: " << storage.get<Object>().size() << '\n'; // 2 
    std::cout << "Things: " << storage.get<Thing>().size() << '\n'; // 3 
    std::cout << "Numbers: " << storage.get<Number>().size() << '\n'; // 2 
    std::cout << "SemiObjects: " << storage.get<SemiObject>().size() << '\n'; // 1 
} 
Verwandte Themen