将可选迭代器传递给函数
Passing an optional iterator to a function
是否可以为函数定义一个可选的迭代器,根据它的存在与否来改变函数的行为?
给出一个具体的例子,考虑定义
template<typename Graph,
typename random_access_iterator_distances,
typename random_access_iterator_predecessors,
typename back_insertor_iterator_frontier,
typename back_insertor_iterator_explored >
void dijkstra(const Graph &g,
const typename boost::graph_traits < Graph >::vertex_descriptor source,
random_access_iterator_distances distances,
random_access_iterator_predecessors predecessors,
const typename boost::graph_traits < Graph >::vertex_descriptor target = -1,
back_inserter_iterator_frontier frontier = null_iterator,
back_inserter_iterator_explored explored = null_iterator );
其中null_iterator
是表示用户不想要此输出的某个值。
通过定义两个单独的函数来解决这个问题,一个具有边界并在定义中探索,另一个没有边界,这不是一个好的选择,因为它需要重复代码(因为函数中的逻辑与frontier
或explored
是否存在紧密耦合)。
是否有某种模式或替代null_iterator
使这种类型的代码在c++中实现?
最简单的解决方案是编写一个简单的DevNullIterator。因为它的operator*
不做任何事情,它被简单地内联并编译掉了。
struct DevNull {
template<typename T> operator=(T const&) { }
template<typename T> operator T&() { static T dummy; return dummy; }
};
struct DevNullIterator {
DevNull operator*() const { return DevNull();}
DevNullIterator operator++() const { return *this; }
};
是否有可能为函数定义一个可选的迭代器,根据它的存在与否来改变函数的行为?
。这是不可能的。有两个候选人;
- 重载。重载创建了一个新的函数(具有相同的名称),所以这不能满足您的需求。
- 默认参数。没有办法区分参数是来自函数的用户还是来自默认值。
感谢KeresSB注释,我最终提出了我认为是一个干净的解决方案。基本上,我使用以下模式:
typedef struct _undefinded {
}undefined_t;
template<typename Graph,
typename random_access_iterator_distances,
typename random_access_iterator_predecessors,
typename back_inserter_iterator_frontier = undefined_t,
typename back_inserter_iterator_explored = undefined_t >
void dijkstra(const Graph &g,
const typename boost::graph_traits < Graph >::vertex_descriptor source,
random_access_iterator_distances distances,
random_access_iterator_predecessors predecessors,
const typename boost::graph_traits < Graph >::vertex_descriptor target = -1,
boost::optional<back_inserter_iterator_frontier> frontier = boost::optional<back_inserter_iterator_frontier>(),
boost::optional<back_inserter_iterator_explored> explored = boost::optional<back_inserter_iterator_explored>() );
然后在函数的代码中,可以检查frontier
或explored
是否用
if ( frontier.is_initialized() ) {
} else {
std::cout << "frontier is uninitialized!" << std::endl;
}
if ( explored.is_initialized() ) {
} else {
std::cout << "explored is uninitialized!" << std::endl;
}
相关文章:
- 如何在C++中将迭代器作为函数参数传递
- 如何在 c++ 中将字符串迭代器变量传递给函数?
- 为什么我的模板化函数需要从一个迭代器转换到另一个迭代器?
- 如何创建迭代器函数
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- 使用迭代器的模板类的构造函数
- C++:复制迭代器的构造函数
- 基于函数而不是集合的二分搜索或迭代器?
- 成员函数中的迭代器出现问题
- 使用迭代器的自定义比较器函数
- 专门C++使用指针值类型的通用迭代器的模板函数?
- 从 std::vector 迭代器中执行函数指针
- 调用 erase() 函数是否也会在擦除元素之前更改迭代器值?
- 如何基于循环迭代器选择函数
- 矢量迭代器在尝试调用函数时使我的程序崩溃
- 成员函数不能为集合迭代器和const_iterator的输入重载(但可以为其他 STL 迭代器重载)
- 具有C++迭代器参数的多功能函数
- C++如何获取传递给函数(STL 迭代器)的参数的名称
- C++ 解释重载成员函数迭代器(int i = 0) 的构造"one liner":i(i) { };