C++98 has front_inserter
, back_inserter
, and inserter
, but there don't seem to be any emplacement versions of these in C++11 or draft C++14. Is there any technical reason we couldn't have front_emplacer
, back_emplacer
, and emplacer
?
Iterators are used to traverse from one element to another element, a process is known as iterating through the container. The main advantage of an iterator is to provide a common interface for all the containers type. Iterators make the algorithm independent of the type of the container used.
Stack does not have iterators, by definition of stack. If you need stack with iterators, you'll need to implement it yourself on top of other container (std::list, std::vector, etc).
Iterators are one of the four pillars of the Standard Template Library or STL in C++. An iterator is used to point to the memory address of the STL container classes.
An iterator is an object that can navigate over elements of STL containers. All iterator represents a certain position in a container. To make it work, iterators have the following basic operations which are exactly the interface of ordinary pointers when they are used to iterator over the elements of an array.
Is there any technical reason we couldn't have front_emplacer, back_emplacer, and emplacer?
No, there is no technical reason. As proof, here is a complete implementation of back_emplacer
with a demo of your Use Case 1...
#include <iterator> #include <vector> #include <iostream> template<class Container> class back_emplace_iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > { protected: Container* container; public: typedef Container container_type; explicit back_emplace_iterator(Container& x) : container(&x) {} template<class T> back_emplace_iterator<Container>& operator=(T&& t) { container->emplace_back(std::forward<T>(t)); return *this; } back_emplace_iterator& operator*() { return *this; } back_emplace_iterator& operator++() { return *this; } back_emplace_iterator& operator++(int) { return *this; } }; template< class Container > inline back_emplace_iterator<Container> back_emplacer( Container& c ) { return back_emplace_iterator<Container>(c); } struct Demo { int i; Demo(int i) : i(i) {} }; int main() { std::vector<int> x = {1,2,3,4,5}; std::vector<Demo> y; std::copy(x.begin(), x.end(), back_emplacer(y)); for (auto d : y) std::cout << d.i << std::endl; }
Possible Known Issue: Does the universal reference of operator=
hide an implicitly generated copy/move operator=
? If so these need to be explicitly defined in a way that beats the universal reference in overload resolution.
Your main use case is already covered by inserter
, back_inserter
and front_inserter
. There is already a value_type &&
overload of operator=
that will move into the container. The only thing emplacer
could do over inserter
is call explicit constructors.
Compare the common overloads of container::insert
, container::push_back
and container::push_front
to container::emplace
, container::emplace_back
and container::emplace_front
iterator insert( const_iterator pos, const value_type & value ); iterator insert( const_iterator pos, value_type && value ); template< class... Args > iterator emplace( const_iterator pos, Args&&... args ); void push_back( const value_type & value ); void push_back( value_type && value ); template< class... Args > void emplace_back( Args&&... args ); void push_front( const value_type & value ); void push_front( value_type && value ); template< class... Args > void emplace_front( Args&&... args );
Each of the emplace
variants takes a pack of arguments with which to construct the value. operator =
takes exactly one argument. You could write an emplacer
that took a tuple of arguments.
template<class Container> class back_emplace_iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > { protected: Container* container; public: typedef Container container_type; explicit back_emplace_iterator(Container& x) : container(&x) {} template<typename ... Args> back_emplace_iterator<Container>& operator=(std::tuple<Args&&...> args) { std::apply(Container::emplace_back, std::tuple_cat(std::tie(*container), std::forward<std::tuple<Args&&...>>(args))); return *this; } back_emplace_iterator& operator*() { return *this; } back_emplace_iterator& operator++() { return *this; } back_emplace_iterator& operator++(int) { return *this; } };
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