Search code examples
c++11c++14compile-timestatic-assert

Static assert to check map, set, unordered_map, unordered_set


I am writing a function where I am copying Keys of map, set, unordered_map, unordered_set to a vector, now I want to add a compile time assert to get clear error if some try to pass a vector, list in that function.

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


}

Any idea how we can do that- as map, unordered_map itself templatized container


Solution

  • You can implement and use is_specialization_of as a generic solution:

    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.


    Note that it can also be used with std::enable_if:

    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.