0

是否可以为函数定义一个可选迭代器,该迭代器将根据函数的存在与否改变函数的行为?

举一个具体的例子,考虑定义

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++ 中实现?

4

3 回答 3

1

最简单的解决方案是编写一个简单的 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; }
};
于 2013-06-06T23:51:44.287 回答
0

感谢 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;   
        }
于 2013-06-07T01:53:19.677 回答
0

是否可以为函数定义一个可选的迭代器,该迭代器将根据函数的存在与否改变函数的行为?

不,这是不可能的。有两个候选人;

  1. 超载。重载会创建一个新函数(同名),所以这不能满足您的需求。
  2. 默认参数。无法区分参数是来自函数的用户还是来自默认值。
于 2013-06-06T23:54:58.250 回答