I have some private class member, representing random access array of std::deque
containing some data:
std::vector<std::deque<SomeDataClass> > someMember;
I would like to provide a public class method which returns iterable data structure, containing all data elements from my array of deques:
std::deque<SomeDataClass> someMethod();
I would like this method go through all the deques in vector and copy every element on it's way to local std::deque, eventually returning this local std::deque by value.
I'm trying to implement this method using C++11 auto
and std::begin()
, std::end()
:
std::deque<SomeDataClass> MyClassName::someMethod(){
std::deque<DirectedEdge> allDataItems;
std::deque<DirectedEdge>::iterator deqIter = allDataItems.begin();
for(auto it = std::begin(someMember); it != std::end(someMember); ++it){
std::copy(std::begin(*it), std::end(*it), deqIter);
}
return allDataItems;
}
I receive data access violation unhandled exception error on runtime in deque header. What is a mistake?
std::copy()
requires the destination range to be large enough to hold the copy, but allDataItems
is empty. You'd have to reserve space in allDataItems
in advance (but that's not possible with std::deque
). You should use a std::back_inserter
(defined in <iterator>
) instead:
std::deque<SomeDataClass> MyClassName::someMethod(){
std::deque<DirectedEdge> allDataItems;
for(auto it = std::begin(someMember); it < std::end(someMember); ++it){
std::copy(std::begin(*it), std::end(*it), std::back_inserter(allDataItems));
}
return allDataItems;
}
Here is an idomatic C+11 way to do it:
std::deque<SomeDataClass> MyClassName::someMethod() {
std::deque<DirectedEdge> allDataItems;
for( auto const& dq : someMember ) {
allDataItems.insert( allDataItems.end(), std::begin(dq), std::end(dq) );
}
return allDataItems;
}
another way would be to write a concatinate
function:
struct concatenate {
template<typename Dest, typename Src>
Dest&& operator()( Dest&& d, Src const& s ) const {
using std::begin; using std::end;
typename std::decay<Dest>::type retval = std::forward<Dest>(d);
retval.insert( end(retval), begin(s), end(s) );
return std::move(retval);
}
};
std::deque<SomeDataClass> MyClassName::someMethod() {
using std::begin; using std::end; // enable ADL
return std::accumulate(
begin(someMember), end(someMember),
std::deque<DirectedEdge>(), concatenate()
);
}
which is pretty cute. If you don't like std::accumulate
,
std::deque<SomeDataClass> MyClassName::someMethod() {
std::deque<DirectedEdge> allDataItems;
for( auto const& dq : someMember ) {
allDataItems = concatenate( std::move(allDataItems), dq );
}
return allDataItems;
}
both of which are roughly equivalently efficient.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With