Elegant path to static_assert (), which is the standard library container type ordered?

In a template function, where one parameter is a standard library container of type T , can I easily statically state that T is an ordered container?

Is there a more elegant way to do this than doing something specific to a particular type, for example, checking for the hash_function() function to distinguish between std::map and std::unordered_map ?

+7
c ++ c ++ 11 stl templates static-assert
source share
4 answers

Another simple one:

 template <template <typename...> class Container> struct is_ordered : std::false_type {}; template <> struct is_ordered<std::map> : std::true_type {}; template <> struct is_ordered<std::set> : std::true_type {}; template <> struct is_ordered<std::multimap> : std::true_type {}; template <> struct is_ordered<std::multiset> : std::true_type {}; 

and then just static_assert(is_ordered<Container>::value, "error") to use it. This is fairly easy to extend for custom containers: just add a line as shown above.

If you do not want to use template templates on the call site, you can always wrap it ala:

 template <typename T> struct is_ordered_2 : std::false_type {}; template <template <typename...> class Container, typename... Ts> struct is_ordered_2<Container<Ts...>> : is_ordered<Container> {}; 

and then you can use it anyway.

+2
source share

This approach is pretty simple:

 // default result template<class T>constexpr bool IsOrdered(const T&) {return false;} // now enumerate the ordered standard library types of interest: template<class K, class T, class C, class A> constexpr bool IsOrdered(const std::map<K,T,C,A>&) {return true;} // ...remaining types... 
+1
source share

If you are only concerned that you have forbidden the use of a pair of specific classes, such as std::unordered_map and std::unordered_set , for example, you can use type traits with static_assert :

 #include <type_traits> #include <unordered_map> #include <unordered_set> template <typename Container, typename T> void func(Container<T> &c) { // make sure that the provided container isn't a type we don't want! static_assert(!std::is_same<Container<T>, std::unordered_map<T>>::value); static_assert(!std::is_same<Container<T>, std::unordered_set<T>>::value); } 

I am not sure if this is of type type or not dependent on your original question. You don’t look at the insides of forbidden classes at all (for example, you are looking for hash_function() , but this method will require you to list containers you don’t want to work with.

0
source share

You could (emphasis on could, because I don't think it's standard) do something like this:

 template <typename T> struct has_typedef_key_compare { // Types "yes" and "no" are guaranteed to have different sizes, // specifically sizeof(yes) == 1 and sizeof(no) == 2. typedef char yes[1]; typedef char no[2]; template <typename C> static yes& test(typename C::key_compare*); template <typename> static no& test(...); // If the "sizeof" of the result of calling test<T>(0) would be equal to sizeof(yes), // the first overload worked and T has a nested type named foobar. static const bool value = sizeof(test<T>(0)) == sizeof(yes); }; template <typename T> struct is_sorted_container { static const bool value; }; template <typename T> const bool is_sorted_container<T>::value = has_typedef_key_compare<T>::value; 

The rationale is that all sorted stl containers (which I looked at) have a key_compare function. Of course, this is NOT a standard. This will NOT cover non-stl types. In general, I do not like it, but I thought that I would publish it as an interesting alternative.

How the stl function works (e.g. std :: upper_bound), this should put a sorted iterator constraint in the comments and let the end user understand this.

0
source share

All Articles