简体   繁体   English

有没有更好的方法来检查STL容器是否是一个多*容器

[英]Is there a better way to check if a STL container is a multi* container

During my work on writing a unit test for a framework that shall work with all kind of standard C++11 container I stepped over the problem that I want to create in a generic way test data. 在我为一个框架编写单元测试的工作期间,该框架应该适用于所有类型的标准C ++ 11容器,我逐步解决了我想要以通用方式创建测试数据的问题。 Here I need to know if an associated container C is a multi* container. 在这里,我需要知道关联的容器C是否是多*容器。 Eg. 例如。 if C is a std::set or a std::multiset. 如果C是std :: set或std :: multiset。 I searched through the interface of all of these containers and all of them have in common that they have an insert(value_type const&) method. 我搜索了所有这些容器的接口,所有这些容器的共同点都是insert(value_type const&)方法。 But from my point of view the significant difference is that the multi* version returns just an iterator, but the 'non' multi* version return a std::pair. 但从我的观点来看,显着的区别是multi *版本只返回一个迭代器,但'non'multi *版本返回一个std :: pair。 So I choose this as differentiator. 所以我选择这个作为区别。

My resulting 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 am not sure if a) this solutions has problems that I do not see so far and b) if there is a more elegant way to write such a trait? 根据这个小测试程序,它似乎工作,但我不确定a)这个解决方案是否有我目前没有看到的问题和b)是否有更优雅的方式来编写这样的特征? I am aware that the trait only works with associative container. 我知道该特征仅适用于关联容器。

Many thanks in advance! 提前谢谢了!

PS.: I have to work with Visual Studio 2010. PS。:我必须使用Visual Studio 2010。

Seeing as there are a small finite number of std::multi* containers, you can just list them: 看到有一小部分std::multi*容器,你可以列出它们:

#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
{};

More lines of code, but it's easy to read and is direct in its reasoning (ie, it definitely works!). 更多行代码,但它易于阅读,并且直接在其推理中(即,它绝对有效!)。

Being an explicit list, the caveat is that it doesn't extend itself automatically. 作为一个明确的清单,需要注意的是它不会自动扩展。 For that, your solution is good. 为此,您的解决方案很好。 C++14 may have an AssociativeContainer concept which would make this even easier; C ++ 14可能有一个AssociativeContainer概念,这将使这更容易; research on this is 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM