Is there a better way to check if an STL container is a multi * container

During my work on writing a unit test for a framework that will work with all the standard C ++ 11 container, I stepped over the problem that I want to create in general test data. Here I need to know if the associated container C is a multi * container. For instance. if C is std :: set or std :: multiset. I was looking at the interface of all these containers and they all have in common that they have an insert (value_type const &) method. But, from my point of view, the significant difference is that the multi * version returns only an iterator, but the 'non' multi * version returns std :: pair. Therefore, I choose this as a differentiator.

My final code is:

#include <type_traits> #include <utility> template <typename Container> class is_multi_container { typedef typename Container::value_type T; typedef typename Container::iterator ExpectedType; typedef decltype(Container().insert(T())) ResultType; public: static const bool value = std::is_same<ResultType, ExpectedType>::value; }; #include <iostream> #include <set> #include <map> #include <unordered_set> #include <unordered_map> int main() { std::cout << "std::set<T> is " << is_multi_container<std::set<int>>::value << std::endl; std::cout << "std::multiset<T> is " << is_multi_container<std::multiset<int>>::value << std::endl; std::cout << "std::map<K,T> is " << is_multi_container<std::map<int,double>>::value << std::endl; std::cout << "std::multimap<K,T> is " << is_multi_container<std::multimap<int,double>>::value << std::endl; std::cout << "std::unordered_set<T> is " << is_multi_container<std::unordered_set<int>>::value << std::endl; std::cout << "std::unordered_multiset<T> is " << is_multi_container<std::unordered_multiset<int>>::value << std::endl; std::cout << "std::unordered_map<K,T> is " << is_multi_container<std::unordered_map<int,double>>::value << std::endl; std::cout << "std::unordered_multimap<K,T> is " << is_multi_container<std::unordered_multimap<int,double>>::value << std::endl; } 

According to this small test program, it seems to work, but I'm not sure that: a) do these solutions have problems that I still don’t see, and b) if there is a more elegant way to write such a sign? I know that this symptom only works with an associative container.

Thank you very much in advance!

PS: I need to work with Visual Studio 2010.

+4
source share
1 answer

When you see that there is a small finite number of std::multi* containers, you can simply list them:

 #include <set> #include <map> #include <unordered_set> #include <unordered_map> #include <type_traits> template <typename Container> struct is_multi_container : std::false_type {}; template <typename T, typename Compare, typename Alloc> struct is_multi_container<std::multiset<T, Compare, Alloc>> : std::true_type {}; template <typename T, typename Compare, typename Alloc> struct is_multi_container<std::multimap<T, Compare, Alloc>> : std::true_type {}; template <typename T, typename Compare, typename Alloc> struct is_multi_container<std::unordered_multiset<T, Compare, Alloc>> : std::true_type {}; template <typename T, typename Compare, typename Alloc> struct is_multi_container<std::unordered_multimap<T, Compare, Alloc>> : std::true_type {}; 

There are more lines of code, but it is easy to read directly in his reasoning (i.e. it definitely works!).

Being an explicit list, the caveat is that it is not automatically distributed. For this, your decision is good. C ++ 14 may have an AssociativeContainer concept that will make this even easier; studies on this issue are left as an exercise for the reader .;)

Example:

 #include <iostream> #include <iomanip> int main() { std::cout << std::boolalpha; #define TEST(type, ...) \ std::cout << type " is: " \ << is_multi_container<__VA_ARGS__>::value \ << std::endl TEST("std::set<T>", std::set<int>); TEST("std::multiset<T>", std::multiset<int>); TEST("std::map<K,T>", std::map<int, double>); TEST("std::multimap<K,T>", std::multimap<int, double>); TEST("std::unordered_set<T>", std::unordered_set<int>); TEST("std::unordered_multiset<T>", std::unordered_multiset<int>); TEST("std::unordered_map<K,T>", std::unordered_map<int, double>); TEST("std::unordered_multimap<K,T>", std::unordered_multimap<int, double>); } 

Output:

 std::set<T> is: false std::multiset<T> is: true std::map<K,T> is: false std::multimap<K,T> is: true std::unordered_set<T> is: false std::unordered_multiset<T> is: true std::unordered_map<K,T> is: false std::unordered_multimap<K,T> is: true 
+4
source

Source: https://habr.com/ru/post/1485120/


All Articles