One line std::vector ctor from mapping another vector? - c++

C++11
There should be a one-line version of the last two lines.
typedef std::pair<T1, T2> impl_node;
std::vector<impl_node> impl;
/* do stuff with impl */
std::vector<T1> retval(impl.size());
std::transform(impl.cbegin(), impl.cend(), retval.begin(),
[](const impl_node& in) { return *in.first; });
I tried writing some sort of custom iterator adapter, and the types are getting hairy. What's the "right" solution? (And it probably generalizes to all sorts of other adapters.)

This is still two lines, but less typing (in both senses):
std::vector<T1> retval(impl.size());
for (const auto& p : impl) retval.push_back(p.first);
Actually, now that I look at it, I'd prefer three lines:
std::vector<T1> retval;
retval.reserve(impl.size());
for (const auto& p : impl) retval.push_back(p.first);
(Edited to remove move because there's no evidence that it's appropriate)

I do not know of a way to do this in one line using only the standard STL from C++11, without writing at least a (templated) helper function first.
You may be looking for a concept where the 2 iterators become one object and C++ starts to support behaviour similar to the LINQ extension methods in .NET:
http://www.boost.org/doc/libs/1_52_0/libs/range/doc/html/index.html

You can get at least half of what you're looking for by using an insert iterator.
Allocate the vector without specifying a size,
std::vector<T1> retval;
...and then populate it by using back_inserter (from #include <iterator>):
std::transform(impl.cbegin(), impl.cend(), back_inserter(retval),[](const impl_node& in) { return *in.first; });

Well, we could start with this:
template<typename Output, typename Input, typename Transformation>
auto transform( Input const& input, Transformation t )->Output {
Output retval;
retval.reserve(input.size());
using std::cbegin; using std::cend;
std::transform(cbegin(input), cend(input), std::back_inserter(retval));
return retval;
}
Then work up to something like this:
namespace aux{
using std::cbegin;
template<typename T>
auto adl_cbegin( T&& t )->decltype(cbegin(std::forward(t)));
}
template<typename Input, typename Transformation>
auto transform_vec( Input const& input, Transformation t )->
std::vector<typename std::remove_ref<decltype(t(*adl_cbegin(input)))>::type>
{
typedef std::vector<typename std::remove_ref<decltype(t(*adl_cbegin(input)))>::type> Output;
Output retval;
// retval.reserve(input.size()); -- need a way to do this if Input has an easy way to get size. Too lazy to bother right now.
using std::cbegin; using std::cend;
std::transform(cbegin(input), cend(input), std::back_inserter(retval));
return retval;
}
Notes: this takes anything iterable (vectors, arrays, pairs of iterators) and produces a
and, from there, upgrade to producing a std::pair of boost::transform_iterator on the input range, so we can then insert the resulting transformation into an arbitrary container, and we only do the transformation work if we actually dereference the iterators.
Or, you know, just use the std::back_inserter(input) directly. :) The downside to that approach is that it doesn't do the reserve, so there are performance hits.

Related

Is there a better way to split a container of a non-movable type based on a predicate

I want to ask for an alternative solution to this problem. I am dealing with this C/C++ style interface that has this non-moveable type NonMovableType defined roughly as follows:
union union_type {
int index;
const char* name;
};
struct NonMovableType
{
std::initializer_list<union_type> data;
};
This is something I cannot change, despite the unfortunate use of unions and initializer lists.
We then have some container of this type, say
std::vector<NonMovableType> container
and we want to split container based on some predicate for each of its members. Now, if it was a movable type i'd do
std::vector<NonMovableType> container;
std::vector<NonMovableType> result;
auto iter = std::partition(container.begin(), container.end(), [](const NonMovableType& element){
return element.data.size(); // the predicate
});
std::move(iter, container.end(), std::back_inserter(result));
container.erase(iter, container.end());
I could then trust container and result would contain the elements split by the predicate, that way I could then iterate over each one individually and do the necessary processing on them.
This wont work however because std::move and std::partition both require a movable type. Instead I have to result to the rather slow:
std::vector<NonMovableType> container;
std::vector<NonMovableType> result_a;
std::vector<NonMovableType> result_b;
std::copy_if(container.begin(), container.end(), std::back_inserter(result_a), [](const NonMovableType& element){
return element.data.size();
});
std::copy_if(container.begin(), container.end(), std::back_inserter(result_b), [](const NonMovableType& element){
return !element.data.size();
});
container.clear();
And so, my question is, is there any better way to do this? I suppose calling it a 'non movable type' may be wrong, its only the union and the initializer list which are giving me problems, so really the question becomes is there a way to move this type safely, and do so without having to change the initial class. Could it also be possible to wrap NonMovableType into another class and then use pointers as opposed to a direct type?
Is it really a performance problem or are you trying to optimize in advance?
As for a general answer: it really depends. I would probably try to achieve everything in a single pass (especially if the original container has a lot of elements), e.g.
for (const auto& el : container) {
if (el.data.size()) out1.push_back(el);
else out2.push_back(el);
}
which can be easily generalized into:
template<typename ForwardIt, typename OutputIt1, typename OutputIt2, typename Pred>
void split_copy(ForwardIt b, ForwardIt e, OutputIt1 out1, OutputIt2 out2, Pred f)
{
for(; b != e; ++b) {
if (f(*b)) {
*out1 = *b;
++out1;
} else {
*out2 = *b;
++out2;
}
}
}
Is this going to be faster than partitioning first and copying later?
I can't tell, maybe. Both solutions are imho ok in terms of readability, as for their performance - please measure and get back with the numbers. :)
Demo:
https://godbolt.org/z/axMsKGq7d
EDIT: operating on heap-allocated objects and vectors of pointers to them, as well as operating on lists is sth. to be verified in practice, for your particular use case. It might help, of course, but again, measure first, optimize later.

Any way to trick std::transform into operating on the iterator themselves?

So I wrote this code which won't compile. I think the reason is because std::transform, when given an iterator range such as this will operate on the type pointed to by the iterator, not the iterator itself. Is there any simple wrapper, standard lib tool, etc. to make this code work i.e. to store all the iterators of the original map into a new vector, with minimum changes required? Thanks!
#include <map>
#include <iostream>
#include <vector>
using MT = std::multimap<char, int>;
using MTI = MT::iterator;
int main()
{
MT m;
m.emplace('a', 1); m.emplace('a', 2); m.emplace('a', 3);
m.emplace('b', 101);
std::vector<MTI> itrs;
std::transform(m.begin(), m.end(), std::back_inserter(itrs), [](MTI itr){
return itr;
});
}
EDIT 1: Failed to compile with gcc11 and clang13, C++17/20
EDIT 2: The purpose of the question is mostly out of curiosity. I want to see what's a good way to manipulate existing standard algorithm to work on the level that I want. The sample code and problem are entirely made up for demonstration but they are not related to any real problem that requires a solution
Is there such a wrapper? Not in the standard. But it doesn't mean you can't write one, even fairly simply.
template<typename It>
struct PassIt : It {
It& operator*() { return *this; }
It const& operator*() const { return *this; }
PassIt & operator++() { ++static_cast<It&>(*this); return *this; }
PassIt operator++(int) const { return PassIt{static_cast<It&>(*this)++}; }
};
template<typename It>
PassIt(It) -> PassIt<It>;
That is just an example1 of wrapper that is a iterator of the specified template parameter type. It delegates to its base for the bookkeeping, while ensuring the the return types conform to returning the wrapped iterator itself when dereferencing.
You can use it in your example to simply copy the iterators
std::copy(PassIt{m.begin()}, PassIt{m.end()}, std::back_inserter(itrs));
See it live
(1) - It relies on std::iterator_traits deducing the correct things. As written in this example, it may not conform to all the requirements of the prescribed iterator type (in this case, we aimed at a forward iterator). If that happens, more boiler-plate will be required.
The function you pass to std::transform and algorithms in general are supposed to use elements not iterators. You could use the key to find the iterator in the map, though thats neither efficient nor simple. Instead use a plain loop:
for (auto it = m.begin(); it != m.end(); ++it) itrs.push_back(it);

Why string_view constructor doesn't take a pair of iterators

Both string_ref in boost and string_span in GSL doesn't define constructor that takes a pair of iterator. What is the reason of this decision ?
Usually it's not a big deal, I can just create string_ref like this :
boost::string_ref s(start, std::distance(start, finish));
but the reason I want constructor that take a pair of iterators is because I have code that look like this:
template<typename Type, typename Iterator>
void func(const Iterator& begin, const Iterator& end)
{
Type s(begin, end);
//do stuff with s
}
Currently, I can call it like this :
func<std::string>(start, finish)
I want to change it to :
func<boost::string_ref>(start, finish) //compile error
but that code won't compile because the lack of constructor taking a pair of iterator in string_ref
boost::string_ref is a simple reference to a string in the form of a pointer to a contiguous block of memory with a predefined length. Since iterators are much more generic, you cannot assume that your start, finish range refers to anything like a contiguous block of memory.
On the other hand, a std::string can be constructed from a range defined by Iterators because it will simply make a copy of the range's values, regardless of what the underlying data structure is.
Helper function I created, hopefully someone else can find this useful. Briefly tested MSVC14/boost 1.59, MSVC17/boost 1.64, MSVC17/C++17
#include <boost/utility/string_ref.hpp>
// todo: change to std::basic_string_view<charT> in C++17
template <typename charT> using basic_string_view_type = boost::basic_string_ref<charT>;
// Creates a string view from a pair of iterators
// http://stackoverflow.com/q/33750600/882436
template <typename _It>
inline constexpr auto make_string_view( _It begin, _It end )
{
using result_type = basic_string_view_type<typename std::iterator_traits<_It>::value_type>;
return result_type{
( begin != end ) ? &*begin : nullptr
, (typename result_type::size_type)
std::max(
std::distance(begin, end)
, (typename result_type::difference_type)0
)
};
} // make_string_view
Looks like I make a mistake. gsl::string_span do have a constructor that takes begin and end iterator. So, there is nothing problematic with creating string_view from iterator pairs and the lack of it in boost::string_ref is probably just an oversight.
For my case, I end up inheriting from boost::string_ref and add the constructor myself.

Simple customized iterator with lambdas in C++

Suppose I have a container which contains int, a function that works over containers containing Point, and that I have a function that given some int gives me the corresponding Point it represents (imagine that I have indexed all the points in my scene in some big std::vector<Point>). How do I create a simple (and efficient) wrapper to use my first container without copying its content?
The code I want to type is something like that:
template<typename InputIterator>
double compute_area(InputIterator first, InputIterator beyond) {
// Do stuff
}
template<typename InputIterator, typename OutputIterator>
void convex_hull(InputIterator first, InputIterator beyond, OutputIterator result) {
// Do stuff
}
struct Scene {
std::vector<Point> vertices;
foo(const std::vector<int> &polygon) {
// Create a simple wraper with limited amount of mumbo-jumbo
auto functor = [](int i) -> Point& { return vertices[polygon[i]]; });
MagicIterator polyBegin(0, functor);
MagicIterator polyEnd(polygon.size(), functor);
// NOTE: I want them to act as random access iterator
// And then use it directly
double a = compute_area(polyBegin, polyEnd);
// Bonus: create custom inserter similar to std::back_inserter
std::vector<int> result;
convex_hull(polyBegin, polyEnd, MagicInserter(result));
}
};
So, as you've seen, I'm looking for something a bit generic. I thought about using lambdas as well, but I'm getting a bit mixed up on how to proceed to keep it simple and user-friendly.
I suggest Boost's Transform Iterator. Here's an example usage:
#include <boost/iterator/transform_iterator.hpp>
#include <vector>
#include <cassert>
#include <functional>
struct Point { int x, y; };
template<typename It>
void compute(It begin, It end)
{
while (begin != end) {
begin->x = 42;
begin->y = 42;
++begin;
}
}
int main()
{
std::vector<Point> vertices(5);
std::vector<int> polygon { 2, 3, 4 };
std::function<Point&(int)> functor = [&](int i) -> Point& { return vertices[i]; };
auto polyBegin = boost::make_transform_iterator(polygon.begin(), functor);
auto polyEnd = boost::make_transform_iterator(polygon.end(), functor);
compute(polyBegin, polyEnd);
assert(vertices[2].y == 42);
}
I didn't quite get the part about custom back_inserter. If the type stored in result vector is the same as what the functor returns, the one from standard library will do. Otherwise you can just wrap it in transform_iterator, too.
Note that the functor is stored in a std::function. Boost relies on the functor to have a typedef result_type defined and lambdas don't have it.
I see two methods. Either start with boost::iterator_facade, then write the "functional iterator" type.
Or, use boost::counting_iterator iterator or write your own (they are pretty easy), then use boost::transform_iterator to map that Index iterator over to your Point iterator.
All of the above can also be written directly. I'd write it as a random access iterator: which requires a number of typedefs, ++, --, a number of +=, -=, -, +s, the comparisons, and * and -> to be defined properly. It is a bit of boilerplate, the boost libraries above just make it a touch less boilerplate (by having the boilerplate within itself).
I've written myself a version of this that takes the function type as an argument, then stores the function alongside the index. It advances/compares/etc using the index, and dereferences using the function type. By making the function type std::function<blah()> I get the type-erased version of it, and by making it a decltype of a lambda argument, or the type of a functor, I get a more efficient version.

C++ less verbose alternative to passing container.start() and container.end()

I declare a vector<Bla> blaVec and write a function:
template<typename Iterator>
void doSomething(Iterator first, Iterator last) { ... }
Then I call this function on blaVec with:
doSomething(blaVec.begin(), blaVec.end());
However, I really would like something shorter like doSomething(blaVec) but without having to specify vector in function definition. Basically, is there a good standard way to specify just the first iterator or maybe a range of [begin,end] iterators as is done by Boost.Range.
I'm an algorithms guy so I really don't want to get into overly generic complex solutions. Most of my life I wrote functions like this:
void doSomething(vector<int> & bla) { ... }
However, these days, I frequently write doSomething that operates on list and deque and vector so a slightly more generic solution was called for, which is why I went with iterators. But it just seems to be too verbose of a solution. What do you suggest?
doSomething(vector & bla) { ... }
doSomething(Iterator first, Iterator last) { ... }
doSomething(/* some range data structure */) { ... }
If you find that verbose, then you can wrap that with this:
template<typename Container>
void doSomething(Container &c)
{
doSomething(c.begin(), c.end()); //internally call the iterator version.
}
And use this function, instead of iterator version.
Also, you can use iterator version, when you don't want the function to operate on all elements in the container. For example,
doSomething(c.begin(), c.begin() + 5); //operate on first 5 elements
//assuming c.begin()+5 makes sense
Prefer the second one, as it is lot more flexible.
I don't feel it is verbose, but if you really insist, you might want to define a macro for it, eg:
#define FULLITER(a) a.begin(), a.end()
(just make sure a is a simple expression so it's not executed twice.)