C++ 使用不同的迭代器避免double for循环中几乎相同的代码重复

C++ 使用不同的迭代器避免double for循环中几乎相同的代码重复,c++,C++,我必须从两种不同的自定义类型构建一个无法更改的图形 由于它们的签名和用途几乎相同,我想删除一些代码副本。 问题是它们返回不同的迭代器 for (auto itFrom = m_pModelSpace->newIterator(); !itFrom->done() && nodesPassed < maxNodes; itFrom->step(), ++nodesPassed) { /* ... */ for (auto it

我必须从两种不同的自定义类型构建一个无法更改的图形
由于它们的签名和用途几乎相同,我想删除一些代码副本。
问题是它们返回不同的迭代器

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())
    {
        /*
        ...
        */
    }
}
for(自动itFrom=m_pModelSpace->newIterator();!itFrom->done()&&nodesPassedstep(),++nodesPassed)
{
/*
...
*/
对于(auto itTo=m_pModelSpace->newIterator();itTo->objectId()!=itFrom->objectId();itTo->step())
{
/*
...
*/
}
}
对于(自动itFrom=m_pSelectionSet->newIterator();!itFrom->done()&&nodesPassednext(),++nodesPassed)
{
/*
...
*/
对于(自动itTo=m_pSelectionSet->newIterator();itTo->objectId()!=itFrom->objectId();itTo->next())
{
/*
...
*/
}
}
注释与代码完全相同。
有办法解决这个问题吗?
我在考虑一个包装器,每个类型有两个构造函数,但是我还需要一个对象迭代器的包装器。
另一个想法是两种类型的多重继承,但这也感觉不太对

有什么建议吗

汇总解决方案
感谢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))
        {
            //...
        }
    }
}
}
名称空间{
ODDBObjectorPTR get_迭代器(OdSmartPtr&pEntityCollection)
{
返回pEntityCollection->newIterator();
}
OdDbSelectionSetIteratorPtr get_迭代器(OdSmartPtr&PenticCollection)
{
返回pEntityCollection->newIterator();
}
无效增量迭代器(ODDBObjectItemOrptr和iter)
{
iter->step();
}
无效增量迭代器(ODDBSelectionSetiterOrptr&iter)
{
iter->next();
}
}
命名空间spax{
模板
void ConnectionGraph::ConstructGraph(集合和奔腾集合,int-maxNodes)
{
// ...
对于(自动itFrom=get_迭代器(pEntityCollection);!itFrom->done()&&NodePassedobjectId()!=itFrom->objectId();增量迭代器(itTo))
{
//...
}
}
}
}
因为选择集返回了OdDbSelectionSetIteratorPtr的父OdSelectionSetIteratorPtr,所以我添加了另一个受此解决方案启发的函数来获取迭代器。
感谢您的帮助,我对结果非常满意。

创建一个函数,该函数以您使用的参数为输入,并将相同的代码放入每个循环中调用,并且

您可以编写一个以
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 );
auto-advance=[](auto&it){it->step()};
自动循环=[&](自动p){
对于(自动itFrom=p->newIterator();!itFrom->done()&&nodesPassednewIterator();itTo->objectId()!=itFrom->objectId();高级(itTo))
{
/*
...
*/
}
}
};
循环(m_pModelSpace);
advance=[](自动&it){it->next()};
循环(m_p选择集);

注意:我将lamdas参数类型更改为
auto
,因为您说过容器类型是不相关的。这适用于c++14或更高版本,否则您可以使用模板。

使用具有间接级别的模板函数来处理迭代器增量怎么样

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))
        {
            /*
            ...
            */
        }
    }
}


在C++中,规范接口(去掉<代码>步骤)( VS <代码> NEXT()>代码>,然后使用模板函数。< /P>是代码相同的MypMealStudio和<代码> MyPopStestOuts相同类型或不同类型的代码?(使用
auto
会使这一点变得非常不清楚)如果它们不同,它们是否有一些共同的基类(或接口)?我假设对象ModelSpace和SelectionSet的newIterator返回类型相同,step()和next()的返回类型也相同;如果是这样的话,将循环放入函数将是使用这些返回类型作为function@UnholySheep注意
itFrom->step()
vs
itFrom->next()
请注意,第二个循环使用
itFrom->next()
,而不是
itFrom->step()
,我想OP指定这两个变量没有共同的类型
WhateverType
。然后参数的
auto
将适用于c++14,或者可以使用模板。是的,第一个和第二个循环使用不同的迭代器下一步和第二步方法。所以这可能只适用于其中一个循环。有什么原因不能工作吗?这似乎是一个显而易见的解决方案。我认为这对一个循环有效,但对两个循环来说似乎很混乱。为什么混乱?这将是完全相同的事情(包含函数的同一行),也许我理解错了,但为了使这项工作,我需要两个函数,因为这是一个双for循环,主要问题在于迭代器具有不同的接口。你能提供一个代码示例吗?这不能解决两个循环中的
步骤
下一步
之间的差异。我添加了一个间接级别来解决这个问题,但接口确实应该是固定的。这看起来很有希望,我明天有一个假期,但我将在周五测试它,如果它能工作,我会接受。由于代码的特殊复杂性,我不得不添加另一个函数,但它工作得非常完美,没有破坏我的任何测试。谢谢你的帮助。正如我所说的,我无法更改接口。
execute_nested_loop(m_pModelSpace);
execute_nested_loop(m_pSelectionSet);