Wie variadische Vorlagen überladen werden, wenn sie nicht das letzte Argument sind

8

Grundsätzlich lässt sich das Problem mit diesem Beispiel zusammenfassen:

%Vor%

Dies ruft die erste foo (Drucke A ) auf. Wie kann ich das zweite foo aufrufen?

Wenn dies eine nicht variadische Vorlage verwendet oder wenn "int" das erste Argument ist, würden die Überladungsregeln die richtige Funktion aufrufen. Das heißt, ein bestimmter Typ ( int ) ist besser als ein Template, so dass er den zweiten foo aufrufen würde. Aber anscheinend ist das bei variadischen Vorlagen nicht der Fall? Gibt es eine Möglichkeit, eine variadische Vorlage zu überladen, wenn es nicht das letzte Argument ist?

    
JoshG79 07.11.2016, 22:14
quelle

3 Antworten

5

Wenn ein Parameterpack nicht zuletzt in der Parameterdeklaration angezeigt wird, handelt es sich um einen nicht abgeleiteten Kontext. Ein nicht-abgeleiteter Kontext bedeutet, dass die Template-Argumente explizit angegeben werden müssen. Deshalb ist foo # 1 eine bessere Überladung. Sie können den zweiten Überlastungsaufruf erzwingen, indem Sie explizite Argumente angeben ( foo<int,int>(1,2,3) ) oder, wie Sie sagten, das int nach vorne verschieben.

Um das klarzustellen, können Sie eine Funktion mit variantenbasierten Vorlagen überladen, aber wenn sie nicht als letztes Argument erscheinen, können sie nicht abgeleitet werden, was sie automatisch als Kandidaten disqualifiziert, wenn explizite Argumente vorliegen nicht zur Verfügung gestellt. Wenn sie bereitgestellt werden, werden die Vorlagenparameter durch ihre bereitgestellten Typen ersetzt und die resultierende Funktion Nichtvorlage ist ein Kandidat in Überladungsauflösung.

Um Ihre Frage zu beantworten, können Sie alle Argumente in ein Tupel setzen und das letzte auswählen und dieses testen. Übergeben Sie dann eine Überladung basierend auf einem einfachen is_same check:

%Vor%     
0x499602D2 07.11.2016, 22:47
quelle
5

Sie könnten SFINAE mit einer% std::tuple -Funktionshilfe (c ++ 11-fähigen Code) verwenden:

%Vor%

Ausgabe:

  

B

Wenn Sie möchten, dass ein anderer Parameter aus dem Paket von einem bestimmten Typ ist, ändern Sie einfach den Parameter std::tuple_element first auf den gewünschten Indexwert.

[Live-Demo]

Wenn Sie auch andere Parameter des Parameterpakets verwenden möchten, z. durch rekursiven Aufruf, dann in größeren Schwierigkeiten ... c ++ 11 kommt nicht mit der Funktionalität des Erstellens von Indexpacks. Sie müssen diese Funktionalität entweder selbst implementieren

%Vor%

[Live-Demo]

oder überprüfen Sie die Parameter Zugriffsmuster:

%Vor%

[Live-Demo]

    
W.F. 07.11.2016 22:33
quelle
1

Die anderen Antworten sind sehr schwer in Bezug auf die Zusammenstellung von Gepäck ( std::tuple ist eine sehr komplexe Vorlage), also, lassen Sie mich Ihnen einen einfachen Weg zeigen.

Zuerst habe ich genau dieses Problem gelöst, ich musste die Reihenfolge der Argumente beibehalten, weil sie woanders erzeugt wurden, und im Allgemeinen ist die Änderung der Reihenfolge der Argumente arbeitsintensiv.

Überladen ist sehr mächtig, aber es macht automatisch Arten von Argumenten schwieriger abzugleiten; Das ist ein Grund, warum es keine partiellen Spezialisierungen von Template-Funktionen gibt. Für die Zwecke Ihrer Benutzerschnittstelle müssen Sie es so einrichten, dass Sie einen Wrapper haben, der entscheidet, ob die Typen in int enden oder nicht. Daher brauchst du dafür eine Typeigenschaft:

%Vor%

Ihre Wahl in Bezug auf ein leeres Typparameterpack.

Dann können Sie:

%Vor%     
EdMaster 29.08.2017 21:41
quelle

Tags und Links