10

ist ein Code-Snippet, das werde ich nutzen, um zu prüfen, ob die variadische Template-Typen sind einzigartig:Wie kann ich diesen variadischen Template-Code mit Features aus C++ 14 und C++ 1z verkürzen? Dieser

template <typename...> 
struct is_one_of; 

template <typename F> 
struct is_one_of<F> { 
    static constexpr bool value = false; 
}; 

template <typename F, typename S, typename... T> 
struct is_one_of<F, S, T...> { 
    static constexpr bool value = 
     std::is_same<F, S>::value || is_one_of<F, T...>::value; 
}; 

template <typename...> 
struct is_unique; 

template <> 
struct is_unique<> { 
    static constexpr bool value = true; 
}; 

template <typename F, typename... T> 
struct is_unique<F, T...> { 
    static constexpr bool value = 
     is_unique<T...>::value && !is_one_of<F, T...>::value; 
}; 

int main() { 
    constexpr bool b = is_unique<bool, int, double>::value; 
    constexpr bool c = is_unique<int, char, int>::value; 
    static_assert(b == true && c == false, "!"); 
} 

Gibt es eine Möglichkeit, dies Code kürzer zu machen und/oder prägnanter mit Funktionen eingeführt in C++ 14 und C++ 1z? Oder gibt es einen besseren Weg, um mit den neuen Funktionen den gleichen Effekt zu erzielen?

Im Fall von C++ 1z meine ich: Funktionen, die bereits in den neuesten Versionen von Clang und GCC verfügbar sind.

+0

Nein, das ist ziemlich prägnant wie es ist. Wenn jedoch Faltungsausdrücke eingeführt werden, können Sie Folgendes tun: 'constexpr statisch bool value = std :: is_same :: value || ... ' –

+1

@BrianRodriguez: Das braucht runde Klammern, denke ich. –

+0

Sie können ein wenig Tricks verwenden, um das 'is_one_of' ein wenig prägnanter zu machen: http://coliru.stacked-crooked.com/a/3b9755f28193a13b – melak47

Antwort

6
#include <type_traits> 

template <typename F, typename... Ts> 
constexpr bool is_one_of = (std::is_same<F, Ts>{} || ...); 

template <typename...> 
constexpr bool is_unique = true; 

template <typename F, typename... Ts> 
constexpr bool is_unique<F, Ts...> = is_unique<Ts...> && !is_one_of<F, Ts...>; 

DEMO

3

würde ich (jetzt) ​​schlagen die std::conj/disj/nega Familie von STL Funktionen:

#include <type_traits> 

template <typename H, typename... T> 
struct is_one_of : std::disjunction<std::is_same<H, T>...> {}; 

template <typename H, typename... T> 
struct is_unique : std::conjunction<std::negation<std::is_same<H, T>>..., is_unique<T...>> {}; 

template <typename H> 
struct is_unique<H> : std::true_type {}; 

int main() 
{ 
    static_assert(is_one_of<int, char, double, int, bool>::value); 
    static_assert(is_unique<int, char, double, bool>::value); 
    static_assert(!is_unique<int, int, char, double, bool>::value); 
} 

Wenn fold-expressions, die für diese Fälle entwickelt wurden, in die Sprache freigegeben werden diese trivial geworden:

namespace stx = std::experimental; 

template <typename H, typename... T> 
struct is_one_of { 
    static constexpr bool value = (stx::is_same_v<H, T> || ...); 
}; 

template <typename H, typename... T> 
struct is_unique { 
    static constexpr bool value = (!stx::is_same_v<H, T> && ... && is_unique<T...>::value); 
}; 

template <typename H> 
struct is_unique<H> : std::true_type {}; 
+0

Ihr 'is_unique' prüft nur, ob' H' eindeutig ist, aber andere 'T's können immer noch Duplikate in der Typenliste haben. – melak47

+1

Dieser Code hat keine Chance zu kompilieren –

+0

Dieser Code ist auf so viele verschiedene Arten gebrochen, dass es klar ist, dass es noch nicht einmal minimal getestet wurde. –

2

Ich bin im Einklang mit den Antworten von Brian Rodriguez und Piotr Scontnincki, soweit es den Teil der Faltenausdrücke betrifft. Bis Falten Ausdrücke sind, könnten Sie den vorhandenen Code ein wenig schrumpfen von der unvollständigen primären Vorlagen Loswerden wie folgt:

template <typename...> 
struct is_one_of { 
    static constexpr bool value = false; 
}; 

template <typename F, typename S, typename... T> 
struct is_one_of<F, S, T...> { 
    static constexpr bool value = 
     std::is_same<F, S>::value || is_one_of<F, T...>::value; 
}; 

template <typename...> 
struct is_unique { 
    static constexpr bool value = true; 
}; 

template <typename F, typename... T> 
struct is_unique<F, T...> { 
    static constexpr bool value = is_unique<T...>::value && !is_one_of<F, T...>::value; 
}; 
9

Wir haben vor kurzem std::disjunction zum C++ hinzugefügt 1z Entwurf, der für is_one_of verwendet werden können (und es stoppt Instanziieren sobald es eine Übereinstimmung findet, finden sie auf den Link für weitere Details):

template <typename F, typename... T> 
    using is_one_of = std::disjunction<is_same<F, T>...>; 

Dies ist bereits in GCC-Trunk implementiert. Bei älteren Versionen von GCC können Sie die Implementierung Detail __or_ statt:

template <typename F, typename... T> 
    using is_one_of = std::__or_<is_same<F, T>...>; 

Oder implementieren disjunction von Hand C++ 11 Einrichtungen verwenden, wie am Ende des Vorschlags oben verlinkten gezeigt.

+0

Das ist super !!! – 101010