Variadische Version von std :: is_convertible?

7

Ist es möglich, eine variadische Version von std::is_convertible zu schreiben? Zum Beispiel würde are_convertible<T1, T2, T3, T4> is_convertible<T1, T3> && is_convertible<T2, T4> zurückgeben. Ich habe einige Stunden darüber nachgedacht, konnte aber nichts Vernünftiges finden.

Um zu verdeutlichen, möchte ich es so verwenden:

%Vor%     
user697683 05.01.2016, 15:41
quelle

3 Antworten

11

Sie müssen Args2... und Args1... nicht verketten, und Sie sollten es nicht tun, da es macht es unmöglich machen zu sagen, wo Args2... endet und Args1... beginnt. Die Möglichkeit, mehrere Variadic-Argumente so zu übergeben, dass sie einzeln extrahiert werden können, besteht darin, sie in eine andere Vorlage einzufügen: Bei einer variadischen Vorlage my_list könnten Sie Ihre my_convertible als

bezeichnen %Vor%

Die Standardbibliothek hat bereits eine variadische Vorlage, die hier gut funktioniert: tuple . Nicht nur das, sondern tuple<Args2...> ist konvertierbar in tuple<Args1...> genau dann, wenn Args2... in Args1... konvertierbar ist, also können Sie einfach schreiben:

%Vor%

Hinweis: In den Kommentaren berichtet @ zatm8, dass dies nicht immer funktioniert: std::is_convertible<std::tuple<const char *&&>, std::tuple<std::string &&>>::value wird als false gemeldet, aber std::is_convertible<const char *&&, std::string &&>::value wird als true gemeldet.

Ich glaube, das ist ein Fehler, der beide als true gemeldet werden sollte. Das Problem ist reproduzierbar auf Ссылка mit clang 3.9.1. Es ist nicht reproduzierbar mit gcc 6.3, und es ist auch nicht reproduzierbar mit clang 3.9.1 bei Verwendung von -stdlib=libc++ . Es scheint, dass libstdc ++ ein Sprachfeature verwendet, das clang nicht ganz korrekt behandelt, und reduziert es auf ein kurzes Beispiel, das nicht auf Standardbibliotheksheadern beruht:

%Vor%

Dies wird von gcc akzeptiert, aber von clang abgelehnt. Es wurde 2014 als Ссылка gemeldet.

Es scheint, dass dies Ende 2016 behoben wurde, aber das Update hat es noch nicht in eine veröffentlichte Version geschafft: Ссылка

Wenn Sie davon betroffen sind, möchten Sie vielleicht std::tuple vermeiden und stattdessen @ Yakks Antwort verwenden.

    
hvd 05.01.2016, 16:16
quelle
7

Ja.

Erstens, wie es geht. Dann, warum sollten Sie es nicht tun.

Wie es geht:

Schreibe eine Neugruppierung, die eine Liste von kN Elementen aufnimmt und sie in N Gruppen von k, verschachtelt gruppiert. Gruppen können template<class...>struct types{}; sein.

Dann schreibe apply, das eine template<class...>class Z und eine class... der Gruppen (aka types<...> ) nimmt und Z auf den Inhalt jedes Bundles anwendet, wobei types<...> des Ergebnisses zurückgegeben wird.

Dann falten Sie den Inhalt von types<...> mit template<class A, class B> struct and_types:std::integral_constant<bool, A{}&&B{}>{}; .

Ich würde das meistens sinnlos finden, also werde ich es nicht umsetzen. Es sollte einfach mit einer anständigen Metaprogrammierungsbibliothek sein, die meisten der oben genannten Operationen sind Standard.

Warum solltest du nicht

Aber wirklich, in Ihrem Beispiel, tun Sie das einfach:

%Vor%

Dann:

%Vor%

erledigt den Job. All das Mischen ist nur Lärm.

Mit der ... Unterstützung von C ++ 1z werden wir auch and_types los und benutzen einfach && und ... .

    
Yakk 05.01.2016 16:00
quelle
0

Sie können std :: concuction verwenden, um alle Ergebnistypen in einem zu falten:

%Vor%

Und denken Sie daran, zu prüfen, ob

%Vor%

mit if conexpr oder enable_if

    
zatm8 26.01.2017 10:26
quelle

Tags und Links