2

std :: vector:でうまく機能するこれらの2つの関数について考えてみます。

  int connectNode(GraphNode const& newNode,std::vector<GraphNode const*>::const_iterator beginCandidates, std::vector<GraphNode const*>::const_iterator endCandidates){
    int connections =0;
    for (auto iter= beginCandidates; iter!=  endCandidates; ++iter) {
      if(connectNodes(newNode,**iter)) ++connections;
    }
    return connections;
  }

  int connectNode(GraphNode const& newNode,std::vector<GraphNode>::const_iterator beginCandidates, std::vector<GraphNode>::const_iterator endCandidates){
    int connections =0;
    for (auto iter= beginCandidates; iter!=  endCandidates; ++iter) {
      if(connectNodes(newNode,*iter)) ++connections;
    }
    return connections;
  }

これらの関数はベクトルに対してはうまく機能しますが、セットなどのその他のコンテナーに対しては明らかに機能しません。それらをどのように一般化することができますか。私が考えることができる唯一の可能な解決策は、いくつかの非常に醜いenable_if回避策を使用することです。簡単な解決策はありますか?編集:明確にするために:通常のコンテナー用とポインターコンテナー用の両方の関数が必要です。実際のロジックは、2つの参照をとるconnetNodes内で発生します。(最初の関数の**に注意してください)

4

2 に答える 2

2

イテレータをテンプレートパラメータとして使用すると、どの種類のコンテナを反復処理するかを心配する必要がなくなります。

template<class T, class Iter>
int connectNode( GraphNode const& newNode, 
                 Iter beginCandidates, 
                 Iter endCandidates )
{
  // ...
}

T他のテンプレートパラメータ( )が関数テンプレートのどこでも使用されているのはわかりませんが、実際のコードではどこかで使用されていると思います。

また、イテレータが使用をstatic_assert指していることもできますGraphNode const*std::iterator_traits<Iter>::value_type

static_assert( std::is_same< typename std::iterator_traits<Iter>::value_type
                             GraphNode const *>::value,
               "Iterator must point to 'GraphNode const *'" );

編集:

GraphNodeいずれかを指すイテレータを受け入れるかGraphNode const *、関数テンプレートの署名を同じままにすることができるようにするために、呼び出しを行うヘルパーに対して2つのオーバーロードを作成しますconnectNodes

bool do_connectNodes( GraphNode const& newNode, GraphNode const *p )
{
  return connectNodes( newNode, *p );
}

bool do_connectNodes( GraphNode const& newNode, GraphNode& n )
{
  return connectNodes( newNode, n );
}

さて、条件をにconnectNode変更しますif

if( do_connectNodes(newNode,*iter) ) ++connections;

イテレータが指しているものに応じて、正しいオーバーロードが選択されます。

于 2013-03-20T22:00:28.407 に答える
2

前述のように、イテレータタイプをテンプレートパラメータにします。これにより、イテレータ自体の一般化の問題が解決されます。通常のGraphNode値とそのポインタを区別するには、オーバーロードを使用できます。

template<class T>
T& maybe_deref(T& v){ return v; }

template<class T>
T& maybe_deref(T* p){ return *p; }

そして、それをで呼び出しますconnectNodes(newNode, maybe_deref(*iter))

于 2013-03-20T22:25:22.417 に答える