2013-06-06 10 views
0

함수의 존재 여부에 따라 함수의 동작을 변경하는 함수에 선택적 반복자를 정의 할 수 있습니까? 선택적 반복자를 함수에 전달

은 구체적인 예는 null_iterator이 출력을 원하지 않는 사용자를 나타내는 일부 값이 될 것입니다 정의

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); 

을 고려해 줄 수 있습니다.

두 개의 분리 된 함수를 정의함으로써이 문제를 해결할 수 있습니다 (하나는 정의에서 탐색되고 다른 하나는 정의되지 않음). 코드의 중복이 필요하기 때문에 좋은 대안이 될 수 없습니다 (함수의 논리 frontier 또는 explored이 있는지 여부와 밀접하게 관련되어 있습니다.

null_iterator의 패턴 또는 대체품이있어 C++에서이 유형의 코드를 실현할 수 있습니까?

+0

로 정의 된 경우 확인할 수 있습니다 :: 선택 '? –

+0

@KerrekSB : 좀 더 자세히 설명해 주시겠습니까? 유망한 솔루션처럼 보입니까? – ldog

+0

글쎄,'boost :: optional '함수 인수를 만든 다음이 함수는 반복자가 전달되었는지 여부를 확인할 수 있습니다. –

답변

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; } 
}; 
+0

그런 다음 일부 알고리즘은'DevNullIterator' 유형의 템플릿 전문화로 더 최적화 할 수 있습니다. 예를 들어, 해당 인수의 출력을 채우기 위해 필요한 일부 함수 호출을 건너 뜁니다. – aschepler

0

그것의 존재 여부에 여부를 기준으로 함수의 동작을 변경하는 함수에 선택적인 반복자를 정의 할 수 있습니까?

아니요. 불가능합니다. 후보자는 두 명입니다.

  1. 과부하. 오버로딩은 새 함수 (이름이 같은)를 생성하므로 사용자의 요구를 충족시키지 못합니다.
  2. 기본 인수. 인수가 함수의 사용자로부터 오는지 또는 디폴트에서 오는지를 구분할 수있는 방법이 없습니다.
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; 
     } 
+0

첫 번째 typedef는 C-ism입니다. – MSalters