如果我有一个类型T
,那么在编译时检查它是否是一种有用的方法,以查看它是否是STL样式的容器(对于任意值类型)?
(假设:指针,参考等已被剥离)
开始代码:
template<class T> // (1)
void f(T&) {}
template<class T> // (2)
void f(std::vector<T>&) {}
void test()
{
int a;
std::vector<int> b;
f(a);
f(b);
}
现在这个工作正常,但如果我想概括容器(即没有明确定义(3),(4),...),该怎么办?
使用SFINAE和类型列表会稍微减少代码,但是有更好的方法吗?
或者是否有基于概念的专业成语?
或者我可以以某种方式利用SFINAE选择性地只启用所需的特化吗?
作为旁注,我不能使用迭代器 - 我试图根据接收T
s作为参数的函数进行专门化。
template<class T>
void f(T&, ...) {
std::cout << "flat" << std::endl;
}
template<class Cont>
void f(Cont& c, typename Cont::iterator begin = Cont().begin(),
typename Cont::iterator end = Cont().end()) {
std::cout << "container" << std::endl;
}
(需要变量参数列表才能使第一个f
最不受欢迎的版本来解决模糊错误)
答案 0 :(得分:2)
你所做的一切几乎肯定是非常脆弱的。什么是或不是“STL”之间根本没有清晰的分界线。即使有一条清晰的分界线,在任何情况下,这种决定几乎肯定都是一个非常糟糕的基础。例如,如果我编写(或使用)std :: map的重新实现,它使用AVL树而不是更常见的R-B树,为什么它应该与std :: map区别对待?
在散列容器的情况下,从hash_map的各种实现,到Boost容器,到TR1容器,再到将包含在C ++ 0x中的标准库中的那些容器,都有一个完整的过程。根据你如何定义“STL”,有一个很好的机会,至少有一个不是STL,而另一个是STL,但是没有一点可以将一个与另一个区别对待。
我认为您应该考虑容器的特性,然后尝试确定对您来说真正重要的特征。
答案 1 :(得分:2)
根据定义,STL容器有一个typedef iterator
,其中包含两个方法begin()
和end()
。此范围是容器包含的内容。如果没有这样的范围,它不是STL意义上的容器。因此,我会根据(未检查)
template<typename CONTAINER>
void f(CONTAINER& c,
typename CONTAINER::iterator begin = c.begin(),
typename CONTAINER::iterator end = c.end())
{ }
答案 2 :(得分:0)