2016-10-25 1 views
1

ich eine Funktion schreibe, wo ich das Kopieren bin Keys von map, set, unordered_map, unordered_set zu einem vector, jetzt möchte ich eine Kompilierung assert hinzufügen klare Fehler zu erhalten, wenn einige versuchen, eine vector, list in dieser Funktion zu übergeben.Static assert Karte zu überprüfen, Satz, unordered_map, unordered_set

template <typename container> 
auto CopyKeyToVector(conatiner c) 
{ 
    //static assert to check c is map, unordered map only? 


} 

Jede Idee, wie wir dass- als map, unordered_map selbst

+0

http://stackoverflow.com/a/31105859/3953764 –

+0

Wenn Sie 'c' verwenden, da es sich um assoziative Container handelt, d. H. Nur eine Elementfunktion aufrufen, die nur in z. 'std :: map' oder' std :: unordered_map', dann erhalten Sie einen Compilerfehler, wenn der Aufrufer etwas übergibt, das diese Memberfunktion nicht besitzt. –

Antwort

3

statische Behauptungen nicht templatized Behälter tun können, verwenden. Verwenden Sie stattdessen eine Dereferenzierungsebene hinzu:

template <typename C> 
void CopyKeyToVectorImpl(const C& c) { /* ... */ } 

template <typename K, typename T, typename Pred, typename Alloc> 
void CopyKeyToVector(const std::map<K, T, Pred, Alloc>& m) { 
    CopyKeyToVectorImpl(m); 
} 

template <typename K, typename T, typename Hash, typename Eq, typename Alloc> 
void CopyKeyToVector(const std::unordered_map<K, T, Hash, Eq, Alloc>& m) { 
    CopyKeyToVectorImpl(m); 
} 

(Sie können die Impl Funktion ändern weitere Sätze in der gleichen Wasch zu ermöglichen, indem der Wert-to-Taste Vorsprung Parametrisierung.)

+1

100% klarer. Compilerfehler sind dein Freund! – erip

+2

Wird die Fehlermeldung nicht ein wortreich sein "kann Überladung nicht finden" im Gegensatz zu der 'static_assert's prägnanten" müssen Karte, unordered_map, ... "Nachricht übergeben? – StoryTeller

+0

@StoryTeller Ein Compiler-Fehler zusammen mit der Verwendung einer Funktion namens CopyKeyToVector sollte definitiv den richtigen Hinweis geben, sollte es nicht sein? Es könnte ein bisschen irreführend sein, wenn man sagt "std :: set" oder ähnliches, aber ich denke, es ist wahrscheinlich klar genug. – erip

5

können Sie implementieren und zu verwenden is_specialization_of als generische Lösung:

template <typename, template <typename...> class> 
struct is_specialization_of : std::false_type 
{ 
}; 

template <template <typename...> class TTemplate, typename... Ts> 
struct is_specialization_of<TTemplate<Ts...>, TTemplate> : std::true_type 
{ 
}; 

template <typename container> 
auto CopyKeyToVector(container c) 
{ 
    static_assert(
     is_specialization_of<container, std::map>{} || 
     is_specialization_of<container, std::unordered_map>{}, ""); 
} 

Full example on wandbox.


Beachten Sie, dass es auch mit std::enable_if verwendet werden können:

template <typename T> 
constexpr auto is_map_or_umap = 
    is_specialization_of<T, std::map>{} || 
    is_specialization_of<T, std::unordered_map>{}; 

template <typename container> 
auto CopyKeyToVector(container) -> std::enable_if_t<is_map_or_umap<container>> 
{ 
    // (1) 
} 

template <typename container> 
auto CopyKeyToVector(container) -> std::enable_if_t<!is_map_or_umap<container>> 
{ 
    // (2) 
} 

int main() 
{ 
    CopyKeyToVector(std::map<int,float>{});   // Calls (1) 
    CopyKeyToVector(std::unordered_map<int,float>{}); // Calls (1) 
    CopyKeyToVector(std::vector<int>{});    // Calls (2) 
} 

Full example on wandbox.

+1

Die Antwort mit den besseren Fehlermeldungen. –