Проблема оптимизации компилятора C ++ для итератора пользовательского цикла - PullRequest
0 голосов
/ 07 июня 2018

Я работаю над частным проектом, у них есть свое собственное содержимое и шаблоны, есть итератор цикла, который они использовали для цикла 'for', выглядит следующим образом:

template<class T> class FakeLoopIter
{
public:
    inline FakeLoopIter(const array<T>& from)
        : m_Curr(((array<T>&)from).begin()), 
        m_End(from.end())
    {
    }

    inline FakeLoopIter(const const_array<T>& from)
        : m_Curr(((const_array<T>&)from).begin()),
        m_End(from.end())
    {
    }

    inline void operator++()
    {
        ++m_Curr; 
    }

    inline void operator++(int)
    {
        ++m_Curr; 
    }

    inline T* current()
    {
        return m_Curr;
    }

    inline const T* end()
    {
        return m_End;
    }   

    inline operator T* ()
    {
        return m_Curr;
    }

    inline ubiBool finished() const
    {
        return m_Curr == m_End;
    }

private:
    T* m_Curr;
    const T* m_End;
};

Есть функция, использующая этот циклитератор, как показано ниже:

void SampleClass::foo()   
{
    int lastLength = 0;
    for(FakeLoopIter<MyCustomClass *> it(m_array); !it.finished(); ++it)
    {
        (*it)->doSomething(this);
        if( (it+1) != it.end()) //optimized out 
        {
            OwnerType src = (*it)->getOwnerInstance();
            OwnerType dst = (*(it+1))->getOwnerInstance();
            lastLength = (src-dst).getLength();
        }
        else
        {
            lastLength = getLastLengthSafely();
        }
        (*it)->setLength( lastLength );
    }

}

После включения оптимизации / O2 логика 'it + 1! = it.end ()' оптимизирована (компилятор считает, что это всегда так), что приводит к сбою.

Если я изменю код, как показано ниже, он будет работать нормально:

void SampleClass::foo()   
{
    int lastLength = 0;
    for(FakeLoopIter<MyCustomClass *> it(m_array); !it.finished(); ++it)
    {
        (*it)->doSomething(this);
        MyCustomClass* dest = *(it + 1);
        if(dest != *(it.end()))
        {
            OwnerType posSource = (*it)->getOwnerInstance();
            OwnerType posDest = dest->getOwnerInstance();
            lastLength = (posSource-posDest).getLength();
        }
        else
        {
            lastLength = getLastLengthSafely();
        }
        (*it)->setLength( lastLength );
    }

}

Буду очень признателен, если кто-нибудь подскажет мне за этим правило оптимизации.

Если что-то неясно по этим вопросам, пожалуйста, дайте мне знать, чтобы я мог их улучшить.

PS: Кстати, я говорю о компиляторе clang.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...