[英]Passing an optional iterator to a function
Is it possible to define an optional iterator to a function that will change the behaviour of the function based on its presence or not? 是否可以为函数定义一个可选的迭代器,该迭代器将根据函数的存在与否更改其行为?
To give a concrete example consider the definition 举一个具体的例子,考虑一下定义
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 );
Where the null_iterator
would be some value that indicates the user does not want this output. null_iterator
是某个值,该值指示用户不需要此输出。
The work-around for this by defining two separate functions, one with frontier and explored in the definition, another without it, would not be a good alternative, because it would require duplication of code (since the logic in the function is tightly coupled with whether either frontier
or explored
is present.) 为此,通过定义两个独立的函数(一个具有边界并在定义中进行了探索,另一个没有该函数)的解决方法将不是一个很好的选择,因为它将需要重复代码(因为该函数中的逻辑与是否存在
frontier
或已explored
。)
Is there somekind of pattern or replacement of null_iterator
to make this type of code realizable in C++? 是否有somekind的模式或替代的
null_iterator
要在C ++这种类型的代码实现的呢?
The easiest solution is to write a simple DevNullIterator. 最简单的解决方案是编写一个简单的DevNullIterator。 Since it's
operator*
doesn't do anything, it's trivially inlined and compiles away. 由于
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; }
};
Is it possible to define an optional iterator to a function that will change the behaviour of the function based on its presence or not?
是否可以为函数定义一个可选的迭代器,该迭代器将根据函数的存在与否更改其行为?
No. This is not possible. 不可以。 There are two candidates;
有两个候选人;
Thanks to KeresSB comment, I ended up coming up with what I think is a clean solution. 感谢KeresSB的评论,我最终提出了我认为是干净的解决方案。 Essentially, I use the following pattern:
本质上,我使用以下模式:
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>() );
Then inside the code of the function, it is possible to check if either frontier
or explored
are defined with 然后该函数的代码的内部,也能够检查是否任一
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.