Klassenvorlagen-Spezialisierung, die alle Versionen von const / volatile Qualifikationen und & vs && akzeptiert

9

Ich spezialisiere std::common_type für meinen Typ. Ich habe folgende Spezialisierung definiert:

%Vor%

Und alles ist gut. Dann kommt jemand vorbei und ruft std::common_type<my_type, my_type &> auf. Die Standardversion verhält sich genauso, wenn Sie eine Referenz im Gegensatz zu einer Referenz übergeben (da sie std::decay für die Typen aufruft). Es wird jedoch nicht auf die Nicht-Referenzversion von std::common_type verwiesen, die ich korrekt arbeiten müsste. Gibt es einen besseren Weg als etwas zu tun (r-Wert-Verweis auf const zur Vereinfachung weglassen):

%Vor%

Sicherlich gibt es einen besseren Weg? Nach meiner Zählung sind das 49 mögliche Versionen, wenn wir const && und const volatile &&

ignorieren

Hinweis: my_type ist eigentlich eine Klassenvorlage, daher sieht die Spezialisierung eher wie

aus %Vor%

Wo das Ergebnis my_type<min(lhs_min, rhs_min), max(lhs_max, rhs_max)>

ist

Die Lösung wäre ziemlich einfach, wenn ich volle Kontrolle über die primären Template-Definitionen hätte, aber ich kann natürlich std::common_type nicht ändern.

    
David Stone 23.11.2013, 19:39
quelle

2 Antworten

2

Soweit ich weiß, müssen Sie nicht beide Seiten der Binärdatei common_type vollständig spezialisieren. Dies ermöglicht die Reduzierung der Spezialisierung auf 12 für eine Seite. Wenn Sie nur einen gemeinsamen Typ zwischen Spezialisierungen von my_type und my_type benötigen, reicht es aus, auf einer Seite zu spezialisieren. Andernfalls müssten Sie sie auf der rechten Seite klonen und 24 Spezialisierungen ergeben.

%Vor%     
dyp 27.11.2013, 19:47
quelle
1

Ich würde vorschlagen, die Spezialisierung ohne die cv- und ref-Qualifiers zu schreiben, und verwende einen Wrapper um std::common_type<> , wie folgt:

%Vor%

Es gibt bereits Spezialisierungen für std::chrono::duration und std::chrono::time_point , die sich nur ohne cv- und ref-Qualifikatoren spezialisieren.

Diese Spezialisierungen werden jedoch nur verwendet, wenn cv- und ref-Qualifikationsmerkmale nicht angegeben sind. Es ist nicht offensichtlich, dass sie nicht verwendet werden, weil

%Vor%

funktioniert gut.

Ich war verwirrt darüber, wie die Spezialisierung verwendet wurde, bis mir klar wurde, dass das nicht der Fall war. Die generische Implementierung von std::common_type<> verwendet decltype() für einen if-else-Ausdruck wie folgt:

%Vor%

Hinweis : Es verwendet SFINAE, um dieses auszuwählen, wenn es erfolgreich ist, andernfalls wird der Typ nicht definiert.

Nun können wir testen, ob dies tatsächlich für std::chrono::duration funktioniert, indem Sie es testen,

%Vor%

was passiert. Jetzt werfen Sie volatile hinein und es bricht ab, genau wie @ Vincent darauf hingewiesen hat, was wiederum beweist, dass die Spezialisierungen nicht verwendet werden.

Also meine Schlussfolgerung ist, dass einer der beiden passieren wird:

  • Die Standardimplementierung wird sich so ändern, dass die Spezialisierungen auch dann verwendet werden, wenn cv- und ref-Qualifier vorhanden sind. In diesem Fall können Sie den CommonType<> -Wrapper wegwerfen, der sowieso trivial ist und den Sie nur definiert haben eine Spezialisierung.
  • Die Standardimplementierung ändert sich nicht, aber Sie haben immer nur eine Spezialisierung definiert und stattdessen CommonType<> verwendet.
mpark 27.11.2013 13:23
quelle