Ich möchte eine has_no_duplicates<...>
Typeigenschaft implementieren, die std::true_type
auswertet, wenn die übergebene variadic Typenliste keine doppelten Typen hat.Verwenden von `void_t`, um mehrfache Vererbungstypwiederholungsfehler zu erkennen
static_assert(has_no_duplicates<int, float>{}, "");
static_assert(!has_no_duplicates<float, float>{}, "");
Nehmen wir an, für den Anwendungsbereich dieser Frage, dass ich das mit Mehrfachvererbung tun wollen.
Wenn eine Klasse aus der gleichen Art mehr als einmal erbt, tritt ein Fehler auf.
template<class T>
struct type { };
template<class... Ts>
struct dup_helper : type<Ts>... { };
// No errors, compiles properly.
dup_helper<int, float> ok{};
// Compile-time error:
// base class 'type<float>' specified more than once as a direct base class
dup_helper<float, float> error{};
Ich nahm an, ich void_t
diese Fehler verwendet haben könnte „erkennen“, aber ich konnte nicht eine funktionierende Lösung following the code samples from cppreference implementieren.
Dies ist, was ich versucht:
template<class, class = void>
struct is_valid
: std::false_type { };
// First try:
template<class T>
struct is_valid<T, std::void_t<decltype(T{})>>
: std::true_type { };
// Second try:
template<class T>
struct is_valid<T, std::void_t<T>>
: std::true_type { };
Für meinen dritten Versuch habe ich versucht, die Erweiterung der dup_helper<...>
mit einem Wrapper-Klasse zu verzögern, die dup_helper
als Vorlage Template-Parameter hat, wie wrapper<dup_helper, ...>
und erweitert es innerhalb von void_t
.
Leider führte alle meine Versuche in den oben genannten Fehler immer Kompilierung verhindert.
Ich nehme an, diese Art von Fehler ist nicht als "Substitutionsfehler" erkennbar, aber ich möchte eine Bestätigung.
Ist diese Art von Fehler tatsächlich nicht mit void_t
zu erkennen? (Wird es immer zu einem Kompilierungsfehler führen?)
Gibt es eine Möglichkeit, es zu erkennen, ohne dass die Kompilierung fehlschlägt? (Oder eine nicht void_t
Abhilfe, die immer noch die Verwendung des „Mehrfachvererbung Tricks“ macht)?
Ich glaube nicht, dass Sie, dass die Arbeit mit Mehrfachvererbung machen. Das Problem ist, dass es nicht die Deklaration von 'dup_helper' ist, die einen Fehler verursacht, sondern seine Definition (wenn ich mich nicht irre). –
Caninonos
@Caninonos Theoretisch wurde Vittorio ein 'T' in' declltype (T {}) 'instanziiert, um dann den Typ zu erhalten. Vittorio hatte gehofft, dass das 'T {}' einen Fehler erzeugen würde, weil die tatsächliche Anweisung 'T {}' ein Fehler ist, selbst wenn der resultierende Typ nicht ist. – Yakk
@Yakk aber 'T {}' erfordert, dass der Compiler 'T' definiert und der Fehler innerhalb seiner Definition liegt. Es ist ein bisschen so, als würde man versuchen, einen Fehler im Textkörper einer Template-Funktion zu finden (statt dessen hinter dem Rückgabetyp/noexcept specifier/default template argument) und es mit sfinae zu "fangen", ich glaube nicht, dass es möglich ist (Ich weiß nicht genau, was der Standard sagt, aber immer noch). (Es gibt auch [this] (http://ideone.com/oT20iI), um eine "Lösung" mit Mehrfachvererbung zu posten. Es ist jedoch völlig unzuverlässig, da es auf EBO und der Größe einer leeren Klasse beruht. t use it) – Caninonos