std::back_inserter for a std::set?
set
doesn't have push_back
because the position of an element is determined by the comparator of the set. Use std::inserter
and pass it .begin()
:
std::set<int> s1, s2;
s1 = getAnExcitingSet();
transform(s1.begin(), s1.end(),
std::inserter(s2, s2.begin()), ExcitingUnaryFunctor());
The insert iterator will then call s2.insert(s2.begin(), x)
where x
is the value passed to the iterator when written to it. The set uses the iterator as a hint where to insert. You could as-well use s2.end()
.
std::inserter with set - insert to begin() or end()?
You could use a custom functor instead of std::inserter
and re-call out.end()
every time a new element is inserted.
Alternatively, if your values are sorted descendingly, out.begin()
will be fine.
Converting std::vector container into an std::set using std::transform
You probably can't create a set of char *
unless all instances of extensionName
with the same value point to the same char array (it would store unique pointers instead of unique values). If you use std::set<std::string>
instead this will both work and only store unique values and solve your variable lifetime problem as std::string
takes care of copying (or moving) itself for you where necessary:
auto lambdaFn =
[](const SomeStruct& x) { return std::string(x.extensionName); };
std::set<std::string> xs;
std::transform(availableExtensions.begin(),
availableExtensions.end(),
std::inserter(xs, xs.begin()),
lambdaFn);
What happens if I use vector::begin() instead of std::back_inserter(vector) for output of set_intersection?
The important requirement for an output iterator is that it be valid and write-able for the range [out, out+
size of output)
.
Passing c.begin()
will lead to the values being overwritten which only works if the container c
holds enough elements to overwrite. Imagine that c.begin()
returns a pointer to an array of size 0 - then you'll see the problem when writing *out++ = 7;
.
back_inserter
adds every assigned value to a vector
(via push_back
) and provides a concise way of making the STL-algorithms extend a range - it overloads the operators that are used for iterators appropriately.
Thus
std::set_intersection(a.begin(),a.end(),b.begin(),b.end(),
c.begin());
invokes undefined behavior once set_intersection
writes something to its output iterator, that is, when the set intersection of a
and b
isn't empty.
Can a conforming implementation silently extend the vector in this case, so that begin() is in fact an appending
OutputIterator
likeback_inserter
is?
Of course. It's undefined behavior. (This is a humorous approach of telling you that you shouldn't even consider using this, no matter the effects on any implementation.)
std::set_intersection and iterators
Yes, You can use std::inserter
, instead of the std::back_inserter
like this.
#include <iterator> // std::inserter
std::set<int> s3;
std::set_intersection(s.begin(), s.end(), s2.begin(), s2.end(),
std::inserter(s3, s3.end()));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Is this correct way to combine std::generate_n and std::back_inserter?
generate_n
requires that its first argument satisfy OutputIterator
, which back_insert_iterator
does (its iterator_category
is output_iterator_tag
).
Potential issues with your code:
std::generate_n(std::back_inserter(mrbig),nitems,[](){return 'a'+(rand()%26);});
- Calling
mrbig.reserve(nitems)
would be more efficient - You should use c++03
std::rand
or c++11uniform_int_distribution<>
from<random>
instead of crand
. - The parentheses
()
between the lambda capture and lambda body are unnecessary for a lambda taking no arguments, although some people prefer them - It is not guaranteed that in implementation character set the letters
a-z
form a contiguous block; for example, in EBCDIC,i
andj
are not adjacent. I believe the only portable form is to store a string"abcd...xyz"
in your program and index into it: How can I write a single for loop running from a to z and A to Z in C?
Why cant I use std::copy with std::string to another std::string?
The problem is r
is an empty std::string
, it contains no char
s. std::copy
is trying to copy-assign char
s since r.begin()
, which leads to UB.
You can make r
containing 5 elements in advance.
std::string r(5, '\0');
Or
std::string r;
r.resize(5);
Or use std::back_inserter
.
std::string r;
std::copy(s.rbegin(),s.rend(), std::back_inserter(r));
Is it safe to use parallel execution policies with std::back_inserter?
Calling push_back
on a std::vector
does not match the requirements of par_unseq
or par
.
So no, it isn't safe.
By saying par
you are promising that access to the iterators used for input and output contains no race conditions. That fails here.
par_unseq
requires more promises from you; basically that you are both data-race free, and your algorithm is suitable for vectorization (doing things in batches).
push_back
does not qualify, and back_inserter
is defined in terms of push_back
.
On the other hand:
std::vector<std::string> src(100, "test"), dst(100, "");
std::move(std::execution::par_unseq, src.begin(), src.end(), dst.begin());
this is valid, because you are allowed to parallel and concurrently access individual elements of a vector
(except vector<bool>
)
Moving a vector into an unordered_set
This solution actually requires more characters, but it does express the intent more directly:
std::unordered_set<T> ht(std::make_move_iterator(v.begin()),
std::make_move_iterator(v.end()));
Why I could use push_back in map but not the back_inserter in set?
my_map[ln].push_back(cn)
does not call push_back
on the map
(my_map
), it calls push_back
on the map
s mapped_type
which is vector<string>
- you access this with operator[]
(my_map[ln]
).
Your statement my_map[ln].push_back(cn)
is essentially equivalent to:
vector<string>& v = my_map[ln];
v.push_back(cn);
Related Topics
How to Block Running Two Instances of the Same Program
Creating Array of Objects on the Stack and Heap
Do Static Members of a Class Occupy Memory If No Object of That Class Is Created
C++11 Rvalue Reference Calling Copy Constructor Too
Read Word by Word from File in C++
Erasing While Iterating an Std::List
Error: 'Int32_Max' Was Not Declared in This Scope
Use of Typename Keyword with Typedef and New
How to Read a File into Vector in C++
Safer But Easy-To-Use and Flexible C++ Alternative to Sscanf()
Stepping into Qt Sources in Qt Creator (In Ubuntu Linux)
Do Pthread Mutexes Work Across Threads If in Shared Memory
Why Don't Std::Vector's Elements Need a Default Constructor
How to Compress Slot Calls When Using Queued Connection in Qt