Hintergrund
Wir wissen, dass das Konzept std::same_as
unabhängig von der Ordnung ist (mit anderen Worten, symmetrisch): std::same_as<T, U>
äquivalent zu std::same_as<U, T>
( verwandte Frage ). In dieser Frage möchte ich etwas Allgemeineres implementieren: template <typename ... Types> concept same_are = ...
Das prüft, ob die Typen im Paket Types
gleich sind.
Mein Versuch
#include <type_traits>
#include <iostream>
#include <concepts>
template <typename T, typename... Others>
concept same_with_others = (... && std::same_as<T, Others>);
template <typename... Types>
concept are_same = (... && same_with_others<Types, Types...>);
template< class T, class U> requires are_same<T, U>
void foo(T a, U b) {
std::cout << "Not integral" << std::endl;
}
// Note the order <U, T> is intentional
template< class T, class U> requires (are_same<U, T> && std::integral<T>)
void foo(T a, U b) {
std::cout << "Integral" << std::endl;
}
int main() {
foo(1, 2);
return 0;
}
(Meine Absicht hier ist es, über jedes mögliche geordnete Paar von Typen in der Packung aufzuzählen)
Leider würde dieser Code nicht kompiliert , und der Compiler beschwert sich, dass der Aufruf von nicht foo(int, int)
eindeutig ist. Ich glaube, dass es betrachtet are_same<U, T>
und are_same<T, U>
als nicht gleichwertig. Ich möchte wissen, warum der Code fehlschlägt, wie ich ihn beheben kann (damit der Compiler sie als gleichwertig behandelt).
quelle
same_with_others
jede mögliche Permutation der Typen ausführt .... Types
sind? Vielleicht kann Ihnen std :: connection helfen. Am Ende der Seite befindet sich ein Beispiel, das Ihrem Ansatz ähnelt.Antworten:
Das Problem ist bei diesem Konzept:
Ist das die normalisierte Form dieses Konzepts ... genau das. Wir können dies nicht "entfalten" (es gibt nichts zu tun), und die aktuellen Regeln normalisieren sich nicht durch "Teile" eines Konzepts.
Mit anderen Worten, damit dies funktioniert, muss sich Ihr Konzept normalisieren in:
in:
Betrachten Sie eine
&&
Einschränkung für Faltausdrücke, um eine andere Einschränkung für Faltausdrücke zu subsumieren,&&
wenn die zugrunde liegende Einschränkung die zugrunde liegende Einschränkung der anderen subsumiert. Wenn wir diese Regel hätten, würde Ihr Beispiel funktionieren.Möglicherweise kann dies in Zukunft hinzugefügt werden. Die Bedenken hinsichtlich der Subsumtionsregeln bestehen jedoch darin, dass Compiler nicht aufgefordert werden müssen, einen vollständigen SAT-Solver zu implementieren, um die Subsumtion von Einschränkungen zu überprüfen. Dieser scheint es nicht viel komplizierter zu machen (wir würden die
&&
und||
Regeln wirklich nur durch Fold-Ausdrücke hinzufügen ), aber ich habe wirklich keine Ahnung.Beachten Sie jedoch, dass selbst wenn wir diese Art von Fold-Expression-Subsumtion hätten,
are_same<T, U>
diese immer noch nicht subsumieren würdestd::same_as<T, U>
. Es würde nur subsumierenare_same<U, T>
. Ich bin mir nicht sicher, ob dies überhaupt möglich wäre.quelle
(... && C<T>)
, das Konzept nicht zu subsumierenC<T>
.((fold1<Ts> && ...) && (fold2<Ts> &&...))
als Konjunktion von(fold1<Ts> && ...)
und(fold2<Ts> && ...)
während es atomar ist.Von cppreference.com Constraint_normalization
Damit
ist "atomar".
Also in der Tat
are_same<U, T>
undare_same<T, U>
sind nicht gleichwertig.Ich sehe nicht, wie ich es implementieren soll :-(
quelle