4

在我为一个适用于所有标准 C++11 容器的框架编写单元测试的工作期间,我跨越了我想以通用方式测试数据创建的问题。在这里,我需要知道关联的容器 C 是否是 multi* 容器。例如。如果 C 是 std::set 或 std::multiset。我搜索了所有这些容器的界面,它们都有一个共同点,即它们都有一个 insert(value_type const&) 方法。但从我的角度来看,显着的区别在于 multi* 版本只返回一个迭代器,但“非”multi* 版本返回一个 std::pair。所以我选择这个作为差异化因素。

我的结果代码是:

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

根据这个小测试程序,它似乎可以工作,但我不确定a)这个解决方案是否存在我到目前为止没有看到的问题,b)是否有更优雅的方式来编写这样的特性?我知道该特征仅适用于关联容器。

提前谢谢了!

PS.:我必须使用 Visual Studio 2010。

4

1 回答 1

4

鉴于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
{};

更多的代码行,但它很容易阅读并且推理很直接(即,它确实有效!)。

作为一个显式列表,需要注意的是它不会自动扩展自身。为此,您的解决方案很好。C++14 可能有一个AssociativeContainer概念可以让这变得更容易;对此的研究留给读者作为练习。;)

例子:

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

输出:

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
于 2013-06-07T22:21:31.770 回答