在我为一个适用于各种标准C ++ 11容器的框架编写单元测试的工作中,我逐步解决了我想要以通用方式创建测试数据的问题。 在这里,我需要知道关联的容器C是否是多*容器。例如。如果C是std :: set或std :: multiset。我搜索了所有这些容器的接口,并且所有这些容器的共同之处在于它们具有insert(value_type const&)方法。但从我的观点来看,显着的区别是multi *版本只返回一个迭代器,但'non'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。
答案 0 :(得分: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