我必须使用两种不同的自定义类型构建图表我无法更改 因为他们的签名和目的几乎相同,所以我想删除一些代码重复 问题是它们返回一个不同的迭代器。
for (auto itFrom = m_pModelSpace->newIterator(); !itFrom->done() && nodesPassed < maxNodes; itFrom->step(), ++nodesPassed)
{
/*
...
*/
for (auto itTo = m_pModelSpace->newIterator(); itTo->objectId() != itFrom->objectId(); itTo->step())
{
/*
...
*/
}
}
for (auto itFrom = m_pSelectionSet->newIterator(); !itFrom->done() && nodesPassed < maxNodes; itFrom->next(), ++nodesPassed)
{
/*
...
*/
for (auto itTo = m_pSelectionSet->newIterator(); itTo->objectId() != itFrom->objectId(); itTo->next())
{
/*
...
*/
}
}
评论的代码完全相同
有什么方法可以解决这个问题吗?
我正在考虑一个包含2个构造函数的包装器,但是我还需要一个包装器用于对象迭代器。
另一个想法是两种类型的多重继承,但也感觉不对。
有什么建议吗?
Summurarized解决方案
感谢Mark B,我得出了以下解决方案:
namespace {
OdDbObjectIteratorPtr get_iterator(OdSmartPtr<OdDbBlockTableRecord>& pEntityCollection)
{
return pEntityCollection->newIterator();
}
OdDbSelectionSetIteratorPtr get_iterator(OdSmartPtr<OdSelectionSet>& pEntityCollection)
{
return pEntityCollection->newIterator();
}
void increment_iterator(OdDbObjectIteratorPtr& iter)
{
iter->step();
}
void increment_iterator(OdDbSelectionSetIteratorPtr& iter)
{
iter->next();
}
}
namespace spax{
template <typename Collection>
void ConnectionGraph::ConstructGraph(Collection& pEntityCollection, int maxNodes)
{
// ...
for (auto itFrom = get_iterator(pEntityCollection); !itFrom->done() && nodesPassed < maxNodes; increment_iterator(itFrom), ++nodesPassed)
{
//...
for (auto itTo = get_iterator(pEntityCollection); itTo->objectId() != itFrom->objectId(); increment_iterator(itTo))
{
//...
}
}
}
}
因为Selection集返回了OdDbSelectionSetIteratorPtr的父OdSelectionSetIteratorPtr,所以我添加了另一个受此解决方案启发的函数来获取迭代器。 感谢您的帮助,我对结果非常满意。
答案 0 :(得分:4)
使用具有间接级别的模板函数来处理迭代器增量怎么样?
void increment_iterator(<model space iterator type>& iter) { iter->step(); }
void increment_iterator(<selection set iterator type>& iter) { iter->next(); }
template <typename Container>
void execute_nested_loop(Container* c)
{
for (auto itFrom = c->newIterator(); !itFrom->done() && nodesPassed < maxNodes; increment_iterator(itFrom), ++nodesPassed)
{
/*
...
*/
for (auto itTo = c->newIterator(); itTo->objectId() != itFrom->objectId(); increment_iterator(itTo))
{
/*
...
*/
}
}
}
然后叫它:
execute_nested_loop(m_pModelSpace);
execute_nested_loop(m_pSelectionSet);
答案 1 :(得分:2)
您可以使用m_pModelSpace
作为参数编写函数。如果您必须从本地上下文传递到该代码中使用的匹配项,请使用lambda:
auto advance = []( auto &it ) { it->step() };
auto loop = [&]( auto p ) {
for (auto itFrom = p->newIterator(); !itFrom->done() && nodesPassed < maxNodes; advance( itFrom ), ++nodesPassed)
{
/*
...
*/
for (auto itTo = p->newIterator(); itTo->objectId() != itFrom->objectId(); advance( itTo ) )
{
/*
...
*/
}
}
};
loop( m_pModelSpace );
advance = []( auto &it ) { it->next() };
loop( m_pSelectionSet );
注意:我将lamdas参数类型更改为auto
,因为您说容器类型不相关。这适用于c ++ 14或更高版本,否则你可以使用模板。
答案 2 :(得分:1)
创建一个函数,将您使用的参数和放置相同代码的位置作为条目,并在每个循环中调用它
答案 3 :(得分:1)
在C ++中,规范化接口(摆脱step()
vs next()
),然后使用模板函数。