特质解决方案。
概括不能超过需要,也不能少于需要。
在某些情况下,该解决方案可能还不够,因为它会匹配具有此类签名的任何模板(例如shared_ptr
),在这种情况下你可以利用type_traits
,非常喜欢鸭子打字 http://en.wikipedia.org/wiki/Duck_typing(模板一般是鸭子类型的)。
#include <type_traits>
// Helper to determine whether there's a const_iterator for T.
template<typename T>
struct has_const_iterator
{
private:
template<typename C> static char test(typename C::const_iterator*);
template<typename C> static int test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
// bar() is defined for Containers that define const_iterator as well
// as value_type.
template <typename Container>
typename std::enable_if<has_const_iterator<Container>::value,
void>::type
bar(const Container &c, typename Container::value_type const & t)
{
// Note: no extra check needed for value_type, the check comes for
// free in the function signature already.
}
template <typename T>
class DoesNotHaveConstIterator {};
#include <vector>
int main () {
std::vector<float> c;
bar (c, 1.2f);
DoesNotHaveConstIterator<float> b;
bar (b, 1.2f); // correctly fails to compile
}
一个好的模板通常可以做到not人为地限制它们有效的类型(为什么要这样做?)。但想象一下在上面的例子中你需要访问一个对象const_iterator
,然后您可以使用 SFINAE 和 type_traits 对您的函数施加这些约束。
或者就像标准库那样
概括不能超过需要,也不能少于需要。
template <typename Iter>
void bar (Iter it, Iter end) {
for (; it!=end; ++it) { /*...*/ }
}
#include <vector>
int main () {
std::vector<float> c;
bar (c.begin(), c.end());
}
有关更多此类示例,请查看<algorithm>
.
这种方法的优点在于它的简单性,并且基于以下概念:前向迭代器。它甚至适用于数组。如果您想直接在签名中报告错误,可以将其与特征结合起来。
std
具有类似签名的容器std::vector
(不建议)
最简单的解决方案已经由 Kerrek SB 近似,尽管它是无效的 C++。更正后的变体如下所示:
#include <memory> // for std::allocator
template <template <typename, typename> class Container,
typename Value,
typename Allocator=std::allocator<Value> >
void bar(const Container<Value, Allocator> & c, const Value & t)
{
//
}
However:这仅适用于具有两个模板类型参数的容器,因此会严重失败std::map
(感谢吕克·丹东)。
任何类型的辅助模板参数(不建议)
任何次要参数计数的更正版本如下:
#include <memory> // for std::allocator<>
template <template <typename, typename...> class Container,
typename Value,
typename... AddParams >
void bar(const Container<Value, AddParams...> & c, const Value & t)
{
//
}
template <typename T>
class OneParameterVector {};
#include <vector>
int main () {
OneParameterVector<float> b;
bar (b, 1.2f);
std::vector<float> c;
bar (c, 1.2f);
}
However:对于非模板容器,这仍然会失败(感谢 Luc Danton)。