Frage

Ich versuche, eine Reihe von Parametern wie folgt an zwei verschiedene Mixin-Klassen weiterzuleiten:

template <typename... Checkers>
class Checker : public Checkers... {
public:
    template<typename... Args>
    Checker(Args&&... args) : Checkers(std::forward<Args>(args))... { }
};

template <typename... Handlers>
class Handler : public Handlers... {
public:
    template <typename... Args>
    Handler(Args&&... args) : Handlers(std::forward<Args>(args))... { }
};

template <typename C, typename H>
class Tester : public C, H {
public:
    template <typename... ArgC, typename... ArgH>
    Tester(std::tuple<ArgC...>&& argc, ArgH&&... argh) : C(argc), H(argh...) {
    }
};

Checker und Handler sind zwei verschiedene Sammlungen von Mixin-Klassen mit unterschiedlichen Anforderungen für jede, aber gemeinsamen Anforderungen für alle Mitglieder.Mir ist klar, dass ich im Tester keine doppelte variadische Konstruktion durchführen kann (der Compiler kann nicht ableiten, wo die Argumente aufgeteilt werden sollen, also übergibt er sie alle an den Handler und keine an den Prüfer), also übergebe ich die Prüferargumente in einem Tupel und die Handlerargumente in eine variadische Liste.Das Problem ist, dass der Konstruktor von Checker dafür verantwortlich ist, diese Parameter an seine Basen weiterzuleiten.Handler kann dies tun, weil der Konstruktor des Handlers eine variadische Liste ist, aber Checker erhält ein Tupel, aber Sie können nicht für jeden die Elemente eines Tupels weiterleiten, wie forward eine variadische Parameterliste.

Jeder Rat wäre sehr dankbar.Danke.

Zusätzlich

Eine Lösung wäre entweder a) auspacken argc in Checkervariadischer Konstruktor oder b) Make Checkerder Konstruktor nimmt ein Tupel und leitet dann irgendwie jedes Element dieses Tupels an jedes von weiter Checkermixin Basen, Checkers....Mir ist klar std::pair hat einen Trick, um ein Tupel als feste Argumentliste an seine Typen weiterzuleiten, z. B. eine 3-parametrische std::vector konstruktor mit dem std::piecewise_construct geben Sie eine Markierung ein, um sie über das Auspacken zu informieren, aber ich sehe nicht, wie dies hier angewendet werden kann.Ich habe mir die Implementierung von GCC 4.8.1 angesehen std::pair mit std::piecewise_construct und konnte es nicht herausfinden.Ich habe einige der älteren Bücher vor C ++ 11 über Template-Metaprogrammierung gelesen (Modernes C ++ - Design und C ++ -Vorlagen-Metaprogrammierung, zum Beispiel), aber ich bin hier jetzt ratlos, da es einen Standard gibt und ich versuche, Boost und Loki zu vermeiden.

Zusätzlich

Muss mindestens entsprechen GCC 4.7.2.Die Lösung, die ich gefunden habe, basiert auf std::pair benötigt Konstruktorvererbung, die erst verfügbar wurde GCC 4.8.1 was auf meinem Build-System nicht unterstützt wird.

Zusätzlich

Obwohl GCC 4.6.3 unterstützung wäre nett, Delegierte Konstrukteure wurden in 4.7.2 hinzugefügt, damit ich Zugriff auf diese Sprachfunktion haben sollte.

War es hilfreich?

Lösung

http://cpptruths.blogspot.fr/2012/06/perfect-forwarding-of-parameter-groups.html

Davidbrczs Lösung, wie in seinem obigen Blog angegeben, reichte aus, um mein Rätsel zu lösen.Die Lösung ist ziemlich komplex, daher leite ich Sie auf seine Seite weiter, aber die Grundidee besteht darin, im laufenden Betrieb ein numerisches Indextupel à la std::maketuple(0, 1, 2, ...), wobei das Tupel jeden der Indizes der verschiedenen Mitglieder des Tupels enthält, die Sie aufzählen müssen.Dann benutzt du einfach:

M(std::forward<ArgM>(std::get<IdxM>(argm))...)

Für M entweder als C oder H im obigen Beispiel und ArgM die Argumente für M und IdxM das gleich große Tupel von Indizes.Da die Listen gleich lang sind, wird die Liste im Tandem in Parameter gerollt und das Tupel wird entpackt.

Die Einschränkung besteht darin, dass Sie möchten, dass der komplizierte Schritt zum Erstellen des Indextupels als Implementierungsdetail ausgeblendet wird. Sie müssen die Konstruktordelegierung so verwenden, dass der öffentliche Konstruktor die 2 Tupel verwendet, die dann an den privaten Konstruktor delegiert werden, der 2 Werttupel und 2 Werte annimmt Indextupel.GCC 4.7.2 unterstützt delegierte Konstruktoren, 4.6.3 jedoch nicht.

Um dies zu umgehen, müssen Sie den 4-Parameter-Konstruktor (2 Tupel von Werten, 2 Tupel von Indizes) öffentlich machen und dann habe ich ein Makro geschrieben, um die Indextupelparameter auszufüllen:

#if __GNUC__ < 4 || __GNUC_MINOR__ <= 6
#define ZEROPARAM , detail::make_indices<>::type()
#define ONEPARAM , detail::make_indices<int>::type()
#define TWOPARAM , detail::make_indices<int, int>::type()
#define THREEPARAM , detail::make_indices<int, int, int>::type()
#define FOURPARAM , detail::make_indices<int, int, int, int>::type()
#define FIVEPARAM , detail::make_indices<int, int, int, int, int>::type()
#define SIXPARAM , detail::make_indices<int, int, int, int, int, int>::type()
#define SEVENPARAM , detail::make_indices<int, int, int, int, int, int, int>::type()
#define EIGHTPARAM , detail::make_indices<int, int, int, int, int, int, int, int>::type()
#define NINEPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int>::type()
#define TENPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int, int>::type()
#else // __GNUC__ < 4 || __GNUC_MINOR__ <= 6
#define ZEROPARAM
#define ONEPARAM
#define TWOPARAM
#define THREEPARAM
#define FOURPARAM
#define FIVEPARAM
#define SIXPARAM
#define SEVENPARAM
#define EIGHTPARAM
#define NINEPARAM
#define TENPARAM
#endif // __GNUC__ < 4 || __GNUC_MINOR__ <= 6

Und fügen Sie dann nach dem Aufbau des angegebenen Testers das entsprechende Makro hinzu, zumindest solange noch Leute auf GCC 4.6.3 sind, während ich daran arbeite, alle auf mindestens 4.7.2 und vorzugsweise 4.8.1 zu bringen.:)

Ich wünschte, ich könnte Davidbrcz Anerkennung für die Lösung zollen, aber zumindest könnte dies für Leute hilfreich sein, die vor einem ähnlichen Problem stehen, um seine Lösung in ihrem speziellen Fall anzuwenden.Die Hauptsache ist, seine make_indices-Vorlagenklasse zu kopieren, um die eigentliche Arbeit zu erledigen;der Rest ist ein Kuchenspaziergang!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top