is back_insert_iterator<> safe to be passed by value?
I have a code that looks something like:
struct Data { int value; };
class A {
public:
typedef std::deque<boost::shared_ptr<Data> > TList;
std::back_in开发者_如何学Csert_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!
}
};
The problem is that A::m_List
is always empty even after CopyInterestingDataTo()
is called. However, if I debug and step into CopyInterestingDataTo()
, the iterator does store the supposedly inserted data!
update: I found the culprit. I actually have something like:
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;
};
Now, which answer should I mark as answer? Really sorry for those not chosen, but you guys definitely got some up-votes : )
The short answer is yes, back_insert_iterator
is safe to pass by value. The long answer: From standard 24.4.2/3:
Insert iterators satisfy the requirements of output iterators.
And 24.1.2/1
A class or a built-in type X satisfies the requirements of an output iterator if X is an Assignable type (23.1) ...
And finally from Table 64 in 23.1:
expression
t = u
return-typeT&
post-conditiont
is equivalent tou
EDIT: At a glance your code looks OK to me, are you 100% certain that elements are actually being inserted? If you are I would single step through the code and check the address of the aa.m_a->m_List
object and compare it to the one stored in outIt
in CopyInterestingDataTo
, if they're not the same something's fishy.
The following code, which compiles, prints "1", indicating one item added to the list:
#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;
}
精彩评论