考虑这两个函数,它们适用于std :: vector:
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解决方法。有直接的解决方案吗? 编辑: 为了更清楚:我想要两个函数,一个用于普通容器,一个用于指针容器。真正的逻辑发生在connetNodes中,它接受两个引用。 (注意第一个函数中的**)
答案 0 :(得分: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 *
的迭代器,使函数模板签名保持不变,但为调用connectNodes
的帮助程序创建2个重载
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;
并根据迭代器指向的内容选择正确的重载。
答案 1 :(得分: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))
中调用它。