返回基于参数类的模板迭代器
Return template iterator based on argument class
我正在编写一个使用迭代器的算法函数。这个函数应该可以与普通迭代器和常量迭代器一起工作,重要的是,这些迭代器来自的类不是模板,我提前知道了。
是否有办法在以下定义中强制迭代器来自特定的类?
// This is an example, A could be any other class with exposed iterators.
using A = std::vector<int>;
// How to enforce that Iterator is an iterator from A?
template <typename Iterator>
Iterator foo(Iterator begin, Iterator end);
...
A a;
auto it = foo(a.begin(), a.end());
*it = 4; // Must compile
// --------
const A a;
auto it = foo(a.begin(), a.end());
*it = 4; // Must not compile
// --------
B b;
auto it = foo(b.begin(), b.end()); // Should not compile.
在这种情况下,foo
不直接修改提供的范围,但如果提供的范围一开始是可修改的,则允许修改结果迭代器。如果这可以在不复制代码的情况下完成,那就太好了。
不要使用template:
A::iterator foo(A::iterator begin, A::iterator end);
您可以使用std::enable_if:
#include <type_traits>
#include <vector>
class X : public std::vector<int> {};
class Y : public std::vector<double> {};
template <typename Iterator>
typename std::enable_if<std::is_same<Iterator, X::iterator>()
|| std::is_same<Iterator, X::const_iterator>(),
Iterator>::type
foo(Iterator begin, Iterator end) {
return begin;
}
int main() {
X x0;
auto i0 = foo(x0.begin(), x0.end());
*i0 = 4; // Must compile
const X x1;
auto i1 = foo(x1.begin(), x1.end());
// error: assignment of read-only location
//*i1 = 4; // Must not compile
Y y;
// error: no type named ‘type’ in ‘struct std::enable_if ...
//auto i2 = foo(y.begin(), y.end()); // Should not compile
}
或static_assert作为更好的替代:
template <typename Iterator>
Iterator foo(Iterator begin, Iterator end) {
static_assert(std::is_same<Iterator, X::iterator>()
|| std::is_same<Iterator, X::const_iterator>(),
"No X::iteator or X::const_iterator");
return begin;
}
可以使用函数重载检查:
inline void check_must_be_iterator_from_A(A::iterator) {}
inline void check_must_be_iterator_from_A(A::const_iterator) {}
template <typename I>
I foo(I a, I b) {
typedef void (*must_be_iterator_from_A)(I);
must_be_iterator_from_A c = &check_must_be_iterator_from_A;
//...
}
另一种选择是使用模板专门化来创建约束,这使得函数内的代码更简洁,并且无论编译器如何,都绝对没有运行时损失:
template <typename I> struct is_iterator_from_A;
template <> struct is_iterator_from_A<A::iterator>{ enum {ok}; };
template <> struct is_iterator_from_A<A::const_iterator>{ enum {ok}; };
template <typename I>
I bar(I a, I b) {
is_iterator_from_A<I>::ok;
return a;
}
我将首先为const迭代器编写函数,然后为non_const情况编写包装器:
A::const_iterator foo(A::const_iterator start, A::const_iterator end) {
std::cout << " Called foo with const iterators " << std::endl;
return start;
}
A::iterator foo(A::iterator start, A::iterator end) {
std::cout << " Called foo with non_const iterators " << std::endl;
auto it = foo(static_cast<A::const_iterator>(start), static_cast<A::const_iterator>(end));
return start + std::distance(static_cast<A::const_iterator>(start), it);
}
如果您内联包装器函数,您应该获得零(或接近零)开销。
编辑:如果您的容器不提供随机访问迭代器distance
具有线性复杂性,您将不得不使用std::advance
而不是"+"操作符,因此根据您的性能要求,这可能不是一个可行的解决方案。
相关文章:
- 如何在C++中将迭代器作为函数参数传递
- 定义模板参数的迭代器类型
- 当通知迭代器参数初始化为空列表的开头时,list::insert 行为是什么?
- 具有C++迭代器参数的多功能函数
- C++如何获取传递给函数(STL 迭代器)的参数的名称
- 当迭代器(输入参数)通常不是constexpr时,constexpr算法真的有用吗
- 迭代器的模板参数:函数在调用时推断类型?
- 接受迭代器作为参数并存储值的类?
- 我的代码在作为参数传入 .begin() 时不起作用,但在我将 .begin() 转换为迭代器后工作
- 如何使用迭代器作为参数方法?
- 调用模板函数的问题"No matching function for call"参数:迭代器、对象函数
- 使用 std::vector<Particle> 粒子;函数 .at() 不能与迭代器一起使用,它作为 for 循环中的参数
- 如何确保函数模板的参数是随机访问迭代器
- 使用迭代器和可变参数模板的笛卡尔乘积
- 从具有迭代器参数的模板函数返回指针
- 英特尔检查器 XE 2012 警告 #12367 - 将迭代器参数切片传递给 vector::erase()
- 容器不可知迭代器参数
- 将可变迭代器参数转换为值类型的元组
- 模板方法中的迭代器参数出现问题
- 为什么标准库函数中没有提供带有迭代器参数的重载?