C++ 将可选迭代器传递给函数
是否可以为函数定义一个可选迭代器,该迭代器将根据函数的存在与否改变函数的行为C++ 将可选迭代器传递给函数,c++,optional-parameters,optional-arguments,C++,Optional Parameters,Optional Arguments,是否可以为函数定义一个可选迭代器,该迭代器将根据函数的存在与否改变函数的行为 给出一个具体的例子,考虑定义 template<typename Graph, typename random_access_iterator_distances, typename random_access_iterator_predecessors, typename back_insertor
给出一个具体的例子,考虑定义
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 );
模板
void dijkstra(常数图和g),
const typename boost::graph_traits::顶点描述符源,
随机访问迭代器距离,
随机访问迭代器,
const typename boost::graph_traits::顶点描述符目标=-1,
back\u inserter\u iterator\u frontier=null\u iterator,
back\u inserter\u iterator\u explored=null\u iterator);
其中,null_迭代器
是表示用户不希望此输出的某个值
通过定义两个单独的函数来解决这一问题,一个带有frontier并在定义中探索,另一个没有frontier,将不是一个好的选择,因为它需要代码的重复(因为函数中的逻辑与是否存在frontier
或explored
紧密耦合)
< > C++中的“代码> Null迭代器< /代码>是否有某种模式或替换,使这类代码在C++中实现?< P>最简单的解决方案是编写一个简单的DevNullIterator。因为它是
操作符*
不做任何事情,所以它只是简单的内联和编译
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; }
};
struct DevNull{
模板运算符=(T常量&){}
模板运算符T&({static T dummy;return dummy;}
};
结构DevNullIterator{
DevNull运算符*()常量{return DevNull();}
DevNullIterator运算符++()常量{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>() );
一个
boost::optional
怎么样?@KerrekSB:你能详细说明一下吗,这看起来是一个很有希望的解决方案?好吧,让函数参数成为boost::optional
,可能是默认的,然后,函数可以检查迭代器是否已传递。然后,一些算法可能能够通过对类型DevNullIterator
的模板专门化进一步优化,例如,跳过一些只需要填充该参数输出的函数调用。第一个typedef是C-ism。
if ( frontier.is_initialized() ) {
} else {
std::cout << "frontier is uninitialized!" << std::endl;
}
if ( explored.is_initialized() ) {
} else {
std::cout << "explored is uninitialized!" << std::endl;
}