假设我们有这个模板
template<typename Container, typename T>
bool contains (const Container & theContainer, const T & theReference) {
...
}
怎么能说,容器中的元素显然应该是T
类型?
这一切都可以缩写吗(可能在 C++11 中)?
最佳答案
虽然使用 value_type
的其他答案是正确的,但此常见问题的规范解决方案是首先不传递容器:使用标准库语义,并且传递一对迭代器。
通过传递迭代器,您不必担心容器本身。您的代码也更加通用:您可以对范围进行操作,您可以使用反向迭代器,您可以将您的模板与其他标准算法等相结合。:
template<typename Iterator, typename T>
bool contains (Iterator begin, Iterator end, const T& value) {
...
}
int main(){
std::vector<int> v { 41, 42 };
contains(std::begin(v), std::end(v), 42);
};
如果要检查Iterator
携带的类型,可以使用std::iterator_traits
:
static_assert(std::is_same<typename std::iterator_traits<Iterator>::value_type, T>::value, "Wrong Type");
(注意这个断言一般是不需要的:如果你提供了一个与T
不可比较的值,模板一开始就不会编译)
最终的模板如下所示:
template<typename Iterator, typename T>
bool contains (Iterator begin, Iterator end, const T& value) {
static_assert(std::is_same<typename std::iterator_traits<Iterator>::value_type, T>::value, "Wrong Type");
while(begin != end)
if(*begin++ == value)
return true;
return false;
}
注意事项:
1) 这应该不足为奇,但我们的 contains
模板现在与 std::find
具有几乎相同的签名。 (返回一个迭代器):
template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );
2)如果修改原contains
的签名太多,可以随时将调用转发到我们的新模板:
template<typename Container, typename T>
bool contains (const Container & theContainer, const T & theReference) {
return contains(std::begin(theContainer), std::end(theContainer), theReference);
}
关于c++ - 如何指示容器模板参数的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27077643/