Wie werden verschachtelte Vorlagenparameter abgeflacht?

Sag ich habe

template pack { };

Ich möchte konvertieren

pack>>>

in

pack

Wie kann ich das machen?

0
nl ja ru
Möchten Sie auch Dinge wie pack , int> konvertieren?
hinzugefügt der Autor Holt, Quelle

4 Antworten

Ich schlage folgende Struktur und Verwendung vor

template 
struct flatt_helper
 { using type = T0; };

template 
struct flatt_helper, T0, Ts2...>
   : flatt_helper, Ts2...>
 { };

template  class C, 
          typename ... Ts2, typename ... Ts3>
struct flatt_helper, C, Ts3...>
   : flatt_helper, Ts2..., Ts3...>
 { };

template 
using flatt = typename flatt_helper, T>::type;

This way you can flatten pack and other template-template, as std::tuple, and also more complex examples (the pack, int> suggested by Holt, by example).

Wenn Sie nur pack verwenden möchten, vermeiden Sie, dass alle Vorlagenvorlagen reduziert werden ... Ich meine ... wenn Sie das möchten

pack>>

wird abgeflacht als

pack>

anstatt

pack

Sie müssen den Parameter template-template in der letzten Spezialisierung flatt_helper entfernen und wie folgt vereinfachen

template 
struct flatt_helper, pack, Ts3...>
   : flatt_helper, Ts2..., Ts3...>
 { };

Das folgende ist ein vollständiges Kompilierungsbeispiel (mit vollständiger Abflachung)

#include 
#include 

template 
struct pack
 { };

template 
struct flatt_helper
 { using type = T0; };

template 
struct flatt_helper, T0, Ts2...>
   : flatt_helper, Ts2...>
 { };

template  class C, 
          typename ... Ts2, typename ... Ts3>
struct flatt_helper, C, Ts3...>
   : flatt_helper, Ts2..., Ts3...>
 { };

template 
using flatt = typename flatt_helper, T>::type;

int main()
 {
   using T0 = pack>>>;
   using T1 = pack;
   using T2 = flatt;
   using T3 = pack, std::tuple, long>>;
   using T4 = pack;
   using T5 = flatt;

   static_assert( std::is_same::value, "!" );
   static_assert( std::is_same::value, "!" );
 }
2
hinzugefügt
@holt würde ich mal "falsch" nennen.
hinzugefügt der Autor Yakk - Adam Nevraumont, Quelle
@Holt - ja, war nicht klar; Antwort modifiziert; Hoffnung ist jetzt klarer
hinzugefügt der Autor max66, Quelle
Nette Antwort mit dem Aufbau von pack <> , aber Sie sollten darauf hinweisen, dass mit dem Parameter template template alles abgeflacht wird, wie flatt < int >>> ist eigentlich pack , was hier möglicherweise nicht das erwartete Verhalten ist.
hinzugefügt der Autor Holt, Quelle

Ich würde alles rekursiv auspacken und zurück packen:

template
struct repack
{
    using type = Head;
};

template
struct repack>>
{
    using type = pack
>; }; 

The type repack>>>>::type get transformed into:

  • pack>>>>
  • pack>>>
  • pack>>
  • pack

Live-Demo

1
hinzugefügt
Dieser Code generiert nicht den Typ, von dem Sie glauben, dass er es tut. Es behandelt auch nicht pack 'int, int, int> richtig.
hinzugefügt der Autor Yakk - Adam Nevraumont, Quelle

Eine mögliche schnelle Implementierung basierend auf std :: tuple_cat :

template 
struct tuple_flatten {
    using type = std::tuple;
};

template 
struct tuple_flatten> {
    using type = decltype(std::tuple_cat(
        typename tuple_flatten::type{}...));
};

template 
struct tuple_to_pack;

template 
struct tuple_to_pack> {
    using type = pack;
};

template 
struct flatten {
    using type = typename tuple_to_pack<
        typename tuple_flatten::type>::type;
};

template 
using flatten_t = typename flatten::type;

Godbolt-Demo

1
hinzugefügt

pack_cat takes a sequence of packs or non-packs, and concatinates anything that is a pack together, plus items that are not packs.

template
struct catter;
template
using pack_cat = typename catter::type;
template
struct catter{ using type=T0; };
template
struct catter, pack, Vs...>{ using type=pack_cat,Vs...>; };
template
struct catter, U, Vs...>{ using type=pack_cat,Vs...>; };

unpacker takes a pack, and recursively unpacks all sub-packs and concatinates them.

template
struct unpacker{using type=X;};
template
using unpack=typename unpacker::type;
template
struct unpacker>{using type=pack_cat,unpack...>;};

Um es zu testen:

pack{}=unpack>>>>{};
pack{} = unpack>{};
pack{} = unpack,int>>{};

Welche IFF-Dateien kompilieren, sind die beiden Typen gleich.

0
hinzugefügt