我有两个类似的功能,即使用图形节点或边缘进行一些计算。
void foo(const VertexMgr& mgr, const std::string name)
{
// Skipped..
for (int i = 0; i< 100; ++i)
{
// Skipped
const A& a = CreateSomething();
for (IterType<Vertex> it = a->vertices(); it != NULL(); ++it)
{
// do something
}
}
}
void goo(const EdgeMgr& mgr, const std::string& name)
{
// Skipped..
for (int i = 0; i< 100; ++i)
{
// Skipped
const A& a = CreateSomething();
for (IterType<Edge> it = a->edges(); it != NULL(); ++it)
{
// do something
}
}
}
问题是:如何在这种情况下摆脱代码重复。 是否有可能的模板解决方案?
答案 0 :(得分:6)
您可以使用Vertex
/ Edge
和manager对象的模板参数,然后使用std::mem_fn
来调用函数。
包装实际的函数调用以使调用更容易。也许像是
template<typename MgrT, typename ItrT, typename FunT>
void foo(const MgrT& mgr, const std::string& name, FunT& fn)
{
for (int i = 0; i < 100; ++i)
{
// Skipped
const A& a = CreateSomething();
for (IterType<ItrT> it = fn(a); it != NULL(); ++it)
{
// do something
}
}
}
void foo(const EdgeMgr& mgr, const std::string& name)
{
foo<EdgeMgr, Edge>(mgr, name, std::mem_fn(&A::edges));
}
void foo(const VerticeMgr& mgr, const std::string& name)
{
foo<VertexMgr, Vertex>(mgr, name, std::mem_fn(&A::vertices));
}
未经测试,但希望能提供一个起点。
答案 1 :(得分:2)
除方法指针外,您可以
template <typename T> IterType<T> GetIterType(A&);
template <> IterType<Vertex> GetIterType<Vertex>(A& a) { return a->vertices(); }
template <> IterType<Edge> GetIterType<Edge>(A& a) { return a->edges(); }
template <typeame Mgr>
void foo(const Mgr& mgr, const std::string name)
{
using itr_type = typename Mgr::itr_type; // That assumes that you add using in Mgr
//else you have to create an external traits.
// Skipped..
for (int i = 0; i < 100; ++i)
{
// Skipped
const A& a = CreateSomething();
for (IterType<itr_type> it = GetIterType<itr_type>(a); it != NULL(); ++it)
{
// do something
}
}
}
另一种方法是使用auto it
代替IterType<..> it
,并使用通用名称重命名(或别名)vertices()
/ edges()
(data()
)。
答案 2 :(得分:1)
这里有一个简单的方法来对这个功能进行构思:
template<class Manager>
void foo(const Manager& mgr, const std::string& name)
{
// Skipped..
for (int i = 0; i< 100; ++i)
{
// Skipped
const A& a = CreateSomething();
for (auto it = Manager::get_iterator(a); it != NULL(); ++it)
{
// do something
}
}
}
以及如何实现get_iterator
:
struct EdgeMgr {
static IterType<Edge> get_iterator(A& a) {
return a.edges();
}
};
struct VertexMgr {
static IterType<Vertex> get_iterator(A& a) {
return a.vertices();
}
};
要进一步使get_iterator
对任何类型都有用,您可以使用模板:
struct EdgeMgr {
template<class T>
static IterType<Edge> get_iterator(T& a) {
return a.edges();
}
};
// ....
Manager::template get_iterator<A>(a)