back_insert_iterator <> безопасно для передачи по значению? - PullRequest
2 голосов
/ 29 марта 2010

У меня есть код, который выглядит примерно так:

struct Data { int value; };
class A {
public:
    typedef std::deque<boost::shared_ptr<Data> > TList;
    std::back_insert_iterator<TList> GetInserter()
    {
        return std::back_inserter(m_List);
    }
private:
    TList m_List;
};
class AA {
    boost::scoped_ptr<A> m_a;
public:
    AA() : m_a(new A()) {}
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        return m_a->GetInserter();
    }        
};
class B {
    template<class OutIt>
    CopyInterestingDataTo(OutIt outIt)
    {
        // loop and check conditions for interesting data
        // for every `it` in a Container<Data*>
        // create a copy and store it
        for( ... it = ..; .. ; ..) if (...) {
            *outIt = OutIt::container_type::value_type(new Data(**it));
            outIt++; // dummy
        }
    }
    void func()
    {
        AA aa;
        CopyInterestingDataTo(aa.GetDataInserter());
        // aa.m_a->m_List is empty!
    }
};

Проблема в том, что A::m_List всегда пусто даже после вызова CopyInterestingDataTo(). Однако, если я отлаживаюсь и перехожу на CopyInterestingDataTo(), итератор сохраняет предположительно вставленные данные!

Обновление: Я нашел виновника. У меня на самом деле есть что-то вроде:

class AA {
    boost::scoped_ptr<A> m_a;
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        //return m_a->GetInserter(); // wrong
        return m_A->GetInserter(); // this is the one I actually want
    }        
    // ..... somewhere at the end of the file
    boost::scoped_ptr<A> m_A;
};

Теперь, какой ответ я должен пометить как ответ? Очень жаль тех, кого не выбрали, но вы, ребята, определенно получили некоторые положительные голоса :)

Ответы [ 2 ]

4 голосов
/ 29 марта 2010

Короткий ответ - да, back_insert_iterator безопасно передавать по значению.Длинный ответ: из стандарта 24.4.2 / 3:

Вставные итераторы удовлетворяют требованиям выходных итераторов.

И 24.1.2 / 1

Класс или встроенный тип X удовлетворяет требованиям выходного итератора, если X является типом Assignable (23.1) ...

И, наконец, из таблицы 64 в 23.1:

выражение t = u тип возврата T& постусловие t эквивалентно u

РЕДАКТИРОВАТЬ: На первый взгляд ваш код выглядит нормально для me , вы на 100% уверены, что элементы на самом деле вставляются?Если вы, я бы пошагово прошел по коду и проверил адрес объекта aa.m_a->m_List и сравнил его с тем, который хранится в outIt в CopyInterestingDataTo, если они не совпадают, что-то подозрительно.

1 голос
/ 29 марта 2010

Следующий код, который компилируется, печатает «1», указывая один элемент, добавленный в список:

#include <iostream>
#include <deque>
#include "boost/shared_ptr.hpp"
#include "boost/scoped_ptr.hpp"

struct Data { 
    int value; 
    Data( int n ) : value(n) {}
};

struct A {
    typedef std::deque<boost::shared_ptr<Data> > TList;
    std::back_insert_iterator<TList> GetInserter()
    {
        return std::back_inserter(m_List);
    }
    TList m_List;
};

struct AA {
    boost::scoped_ptr<A> m_a;
    AA() : m_a(new A()) {}
    std::back_insert_iterator<A::TList> GetDataInserter()
    {
        return m_a->GetInserter();
    }        
};

struct B {
    template<class OutIt>
    void CopyInterestingDataTo(OutIt outIt)
    {
        *outIt = typename OutIt::container_type::value_type(new Data(0));
        outIt++; // dummy
    }
    int func()
    {
        AA aa;
        CopyInterestingDataTo(aa.GetDataInserter());
        return aa.m_a->m_List.size();
    }
};

int main() {
    B b;
    int n = b.func();    
    std::cout <<  n << std::endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...