How can I wrap an OutputIterator such as back_inserter_iterator with a transformation?
Consider
std::vector<double> xx;
std::vector<double> yy;
std::vector<double> diff;
auto ba = std::back_inserter(diff);
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(), ba);
I would like to apply a free function f(double) or g(std::vector<double>::iterator) before pushing back to the diff vector:
Specifically, how can I store the addresses of the diff elements (or iterators) instead of the elements themeselves.
std::vector<double&> diff;
auto baAdr = ??? std::back_inserter( ??? (diff));
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(), baAdr);
For performance reasons (the real data is big) I do not want to construct a temporary vector and std::transform from it. It would also not work for non-copyable, movable types.
I can use boost.
With boost::function_output_iterator:
#include <vector>
#include <algorithm>
#include <boost/function_output_iterator.hpp>
int main()
{
std::vector<double> xx;
std::vector<double> yy;
std::vector<const double*> diff; // const pointers, or else you
// need a const_cast in lambda
std::set_difference(xx.begin(), xx.end(), yy.begin(), yy.end(),
boost::make_function_output_iterator(
[&diff](const double& d) { diff.push_back(&d); }
)
);
}
There's probably something built in to boost, but here's my hacky attempt to write my own iterator:
template <typename T, typename FN>
struct transform_iterator {
transform_iterator(T &t, FN fn)
: _t{t}
, _fn{std::move(fn)} { }
transform_iterator<T, FN>& operator * () { return *this; }
transform_iterator<T, FN>& operator ++ () { return *this; }
template <typename V>
transform_iterator<T, FN>& operator = (V const &v) {
_t.push_back(_fn(v));
return *this;
}
T &_t;
FN _fn;
};
This will take a function and execute it whenever something tries to assign to the iterator (I think this is how things like back_inserter usually work). A trivial helper function can create the iterators:
template <typename T, typename FN>
auto make_transform_iterator(T &t, FN fn) {
return transform_iterator<T, FN>{t, std::move(fn)};
};
Lastly, iterator_traits needs to be specialized so transform_iterator will work with algorithms.
namespace std {
template <typename T, typename FN>
struct iterator_traits<transform_iterator<T, FN>> {
using value_type = typename T::value_type;
};
}
There are more types that need to be set in iterator_traits, but this was sufficient for my testing; your mileage will vary.
My main looks like this:
int main() {
std::vector<int> xx{1, 2, 3};
std::vector<int> yy{1, 3, 5};
std::vector<int> diff;
auto ba = make_transform_iterator(diff, [](auto v) { return v + 10; });
std::set_difference(std::begin(xx), std::end(xx),
std::begin(yy), std::end(yy),
ba);
for(auto const &v: diff) {
std::cout << v << '\n';
}
return 0;
}
You could expand this to work with generic output iterators instead of just types that support push_back.
Related
i want to initialize a const std::vector<int> member variable in the initializer list of a constructor, given a std::vector<std::tuple<int, float>> constructor argument. The vector should contain all the first tuple items.
Is there a one-liner that extracts an std::vector<int> containing all the first tuple entries from an std::vector<std::tuple<int, float>> ?
With C++20 ranges:
struct X
{
const std::vector<int> v;
template <std::ranges::range R>
requires std::convertible_to<std::ranges::range_value_t<R>, int>
X(R r)
: v{r.begin(), r.end()}
{}
X(const std::vector<std::tuple<int, float>>& vt)
: X{vt | std::ranges::views::elements<0>}
{}
};
With ranges-v3:
struct X
{
const std::vector<int> v;
X(const std::vector<std::tuple<int, float>>& vt)
: v{vt | ranges::views::transform([] (auto t) {
return std::get<0>(t); })
| ranges::to<std::vector>()}
{}
};
And a Frankenstein's monster:
#include <ranges>
#include <range/v3/range/conversion.hpp>
struct X
{
const std::vector<int> v;
X(const std::vector<std::tuple<int, float>>& vt)
: v{vt | std::ranges::views::elements<0>
| ranges::to<std::vector>()}
{}
};
Not a one-liner to setup, but certainly one to use - you can write a function to do the conversion, and then the constructor can call that function when initializing the vector member, eg:
std::vector<int> convertVec(const std::vector<std::tuple<int, float>> &arg)
{
std::vector<int> vec;
vec.reserve(arg.size());
std::transform(arg.begin(), arg.end(), std::back_inserter(vec),
[](const std::tuple<int, float> &t){ return std::get<int>(t); }
);
return vec;
}
struct Test
{
const std::vector<int> vec;
Test(const std::vector<std::tuple<int, float>> &arg)
: vec(convertVec(arg))
{
}
};
Adding to #bolov's answer, let's talk about what you might have liked to do, but can't in a one-liner.
There's the to<>() function from ranges-v3 from #bolov 's answer - it materializes a range into an actual container (a range is lazily-evaluated, and when you create it you don't actually iterate over the elements). There is no reason it shouldn't be in the standard library, if you ask me - maybe they'll add it 2023?
You may be wondering - why do I need that to()? Can't I just initialize a vector by a range? And the answer is - sort of, sometimes, maybe. Consider this program:
#include <vector>
#include <tuple>
#include <ranges>
void foo()
{
using pair_type = std::tuple<int, double>;
std::vector<pair_type> tvec {
{12, 3.4}, {56, 7.8}, { 90, 91.2}
};
auto tv = std::ranges::transform_view(
tvec,
[](const pair_type& p) { return std::get<0>(p);}
);
std::vector<int> vec1 { tv.begin(), tv.end() };
std::vector<std::tuple<int>> vec2 {
std::ranges::transform_view{
tvec,
[](const pair_type& p) { return std::get<0>(p);}
}.begin(),
std::ranges::transform_view{
tvec,
[](const pair_type& p) { return std::get<0>(p);}
}.end()
};
}
The vec1 statement will compile just fine, but the vec2 statement will fail (GodBolt.org). This is surprising (to me anyway)!
You may also be wondering why you even need to go through ranges at all. Why isn't there a...
template <typename Container, typename UnaryOperation>
auto transform(const Container& container, UnaryOperation op);
which constructs the transformed container as its return value? That would allow you to write:
std::vector<int> vec3 {
transform(
tvec,
[](const pair_type& p) { return std::get<0>(p); }
)
}
... and Bob's your uncle. Well, we just don't have functions in the C++ standard library which take containers. It's either iterator pairs, which is the "classic" pre-C++20 standard library, or ranges.
Now, the way I've declared the transform() function, it is actually tricky/impossible to implement generally, since you don't have a way of converting the type of a container to the same type of container but with a different element. So, instead, let's write something a little easier:
template <
typename T,
template <typename> class Container,
typename UnaryOperation
>
auto transform(const Container<T>& container, UnaryOperation op)
{
auto tv = std::ranges::transform_view(container, op);
using op_result = decltype(op(*container.begin()));
return Container<op_result> { tv.begin(), tv.end() };
}
and this works (GodBolt.org).
Yes, there is a one-liner if you use this library in Github.
The code goes like this.
#include <iostream>
#include <tuple>
#include <vector>
#include <LazyExpression/LazyExpression.h>
using std::vector;
using std::tuple;
using std::ref;
using std::cout;
using LazyExpression::Expression;
int main()
{
// Define test data
vector<tuple<int, float>> vecTuple { {1,1.1}, {2,2.2}, {3, 3.3} };
// Initialize int vector with the int part of the tuple (the one-liner :)
vector<int> vecInt = Expression([](const tuple<int, float>& t) { return std::get<int>(t); }, ref(vecTuple))();
// print the results
for (int i : vecInt)
cout << i << ' ';
cout << "\n";
}
// Output: 1 2 3
I have a vector<T> input from which I want to get n randomly selected elements via the std::sample algorithm from STL C++17 (http://en.cppreference.com/w/cpp/algorithm/sample). The code works fine in case results is of type vector<T>.
Code example 1 (no pointers returned)
auto getSamples(unsigned int noSamples, const vector<T> &input)
{
vector<T> results;
std::mt19937 twisterEngine;
std::sample(input.begin(), input.end(), std::back_inserter(results),
noSamples, twisterEngine);
return results;
}
However, I am looking not for values/copies of the elements stored in input but I would like to get pointers to the n sampled elements. Are there any tips how I can get pointer returned by vector<T*> results using only standard c++ code (e.g. not using boost library, etc.)? How do I need to adjust following code to get it done?
Code example 2 (intention to get pointers returned)
auto getSamples(unsigned int noSamples, const vector<T> &input)
{
vector<T*> results;
std::mt19937 twisterEngine;
std::sample(input.begin(), input.end(), std::back_inserter(results),
noSamples, twisterEngine);
return results;
}
You just need an OutputIterator. It doesn't actually have to emit something as if it were an iterator. It could just... do something else entirely. Like, invoke a function.
#include <iterator>
template <class F>
struct function_output_iterator {
F f;
using iterator_category = std::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
function_output_iterator& operator++() { return *this; }
function_output_iterator& operator*() { return *this; }
function_output_iterator& operator++(int) { return *this; }
template <class U,
std::enable_if_t<!std::is_base_of<
function_output_iterator, std::decay_t<U>>{}, int> = 0>
void operator=(U&& u) {
f(std::forward<U>(u));
}
};
template <class F>
function_output_iterator(F ) -> function_output_iterator<F>;
And then, you can do whatever arbitrary operation you want:
auto getSamples(unsigned int noSamples, const vector<T> &input)
{
vector<T*> results;
results.reserve(noSamples);
std::mt19937 twisterEngine;
std::sample(input.begin(), input.end(),
function_output_iterator{[&](T const& elem){ results.push_back(&elem); }, // <==
noSamples, twisterEngine);
return results;
}
In order to broaden my understanding of C++11, I'm experimenting with writing functional helpers and seeing if I can make calling them less verbose. Consider the following code:
#include <list>
int timesTwo(int x) { return x*2; }
int timesX(int x, int y) { return x*y; }
class Foo {
public:
Foo(int a) : value(a) {};
int fooTimesTwo() const { return value*2; };
int value;
};
template <class T, class U>
std::list<U> myMap(const std::list<T> &list, const std::function<U(const T &)> &func)
{
std::list<U> result;
for(typename std::list<T>::const_iterator it = list.begin(); it != list.end(); ++it) {
result.push_back(func(*it));
}
return result;
}
int main()
{
std::list<int> numbers = {1,2,3,4,5};
std::list<int> numbers2 = myMap<int,int>(numbers, [] (int x) { return x*2; });
std::list<int> numbers3 = myMap<int,int>(numbers, ×Two);
std::list<int> numbers4 = myMap<int,int>(numbers, std::bind(timesX, 2, std::placeholders::_1));
std::list<Foo> fooList = {Foo(1), Foo(2), Foo(3), Foo(4)};
std::list<int> numbers5 = myMap<Foo,int>(fooList, &Foo::fooTimesTwo);
return 0;
}
Is there anyway to rewrite myMap so that
all four of the calls to it in my code example do not require any template arguments, and...
there's only one general implementation, and I don't have to manually write an overloaded version for each combination of types I want to call it with?
I've tried changing the second argument of myMap to be a third templated type instead of std::function, but it fails because a) the second templated type U can't be inferred, and b) even if it could, the fourth call to myMap will cause an error on line 20 due to &Foo::fooTimesTwo not being a function or function pointer.
I'm willing to consider all of the various features of C++11 to do this, and I don't particularly care if it makes the declaration or definition of myMap obtuse or unreadable. I'm just wondering if it's possible and, if so, what sort of techniques and C++11 features can accomplish it.
You could attempt to implement std::invoke in C++11, but I think it would be really cumbersome.
It's fairly simple to make a function template for a generalized callable:
template <class T, class F>
auto myMap(const std::list<T> &list, F&& func)
-> std::list<typename std::decay<decltype(func(*list.begin()))>::type>
{
using U = typename std::decay<decltype(func(*list.begin()))>::type;
std::list<U> result;
for(typename std::list<T>::const_iterator it = list.begin(); it != list.end(); ++it) {
result.push_back(func(*it));
}
return result;
}
You get expression sfinae for free. Now there's only member function pointer to be taken care of:
template <class T, class F>
auto myMap(const std::list<T> &list, F&& func)
-> std::list<typename std::decay<decltype(((*list.begin()).*func)())>::type>
{
return myMap(list, [=](T const& t){ return (t.*func)(); });
}
Now you can call your functions as expected. demo
While at it, you could replace this ugly for loop with a ranged for:
for(auto const& elem : list) {
results.push_back(func(elem));
}
Or use an algorithm:
std::transform(list.begin(), list.end(), std::back_inserter(result), func);
I have trouble describing my problem so I'll give an example:
I have a class description that has a couple of variables in it, for example:
class A{
float a, b, c, d;
}
Now, I maintain a vector<A> that contains many of these classes. What I need to do very very often is to find the object inside this vector that satisfies that one of it's parameters is maximal w.r.t to the others. i.e code looks something like:
int maxi=-1;
float maxa=-1000;
for(int i=0;i<vec.size();i++){
res= vec[i].a;
if(res > maxa) {
maxa= res;
maxi=i;
}
}
return vec[maxi];
However, sometimes I need to find class with maximal a, sometimes with maximal b, sometimes the class with maximal 0.8*a + 0.2*b, sometimes I want a maximal a*VAR + b, where VAR is some variable that is assigned in front, etc. In other words, I need to evaluate an expression for every class, and take the max. I find myself copy-pasting this everywhere, and only changing the single line that defines res.
Is there some nice way to avoid this insanity in C++? What's the neatest way to handle this?
Thank you!
I know this thread is old, but i find it quite useful to implement a powerful argmax function in C++.
However, as far as i can see, all the given examples above rely on std::max_element, which does comparison between the elements (either using a functor or by calling the operator<). this can be slow, if the calculation for each element is expensive. It works well for sorting numbers and handling simple classes, but what if the functor is much more complex? Maybe calculating a heuristic value of a chess position or something else that generate a huge tree etc.
A real argmax, as the thread starter mentioned, would only calculate its arg once, then save it to be compared with the others.
EDIT: Ok i got annoyed and had too much free time, so i created one < C++11 and one C++11 version with r-value references, first the C++11 version:
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
template<typename IteratorT, typename HeuristicFunctorT>
IteratorT argmax(IteratorT && it, const IteratorT & end, const HeuristicFunctorT & functor) {
IteratorT best(it++);
typename HeuristicFunctorT::result_type best_value(functor(*best));
for(; it != end; ++it) {
typename HeuristicFunctorT::result_type value(functor(*it));
if (value > best_value) {
best_value = value;
best = it;
}
}
return best;
}
template<typename IteratorT, typename HeuristicFunctorT>
inline IteratorT argmax(const IteratorT & begin, const IteratorT & end, const HeuristicFunctorT & functor) {
return argmax(IteratorT(begin), end, functor);
}
class IntPairFunctor : public std::unary_function< std::pair<int, int>, int > {
public:
int operator() (const std::pair<int, int> & v) const {
return v.first + v.second;
}
};
std::pair<int, int> rand_pair() {
return std::make_pair(rand(), rand());
}
int main(int argc, const char **argv) {
srand(time(NULL));
std::vector< std::pair<int, int> > ints;
std::generate_n(std::back_insert_iterator< std::vector< std::pair<int, int> > >(ints), 1000, rand_pair);
std::vector< std::pair<int, int> >::iterator m (argmax(ints.begin(), ints.end(), IntPairFunctor()));
std::cout << std::endl << "argmax: " << *m << std::endl;
}
The non C++11 version is much simpler, only the template:
template<typename IteratorT, typename HeuristicFunctorT>
IteratorT argmax(IteratorT it, const IteratorT & end, const HeuristicFunctorT & functor) {
IteratorT best(it++);
typename HeuristicFunctorT::result_type best_value(functor(*best));
for(; it != end; ++it) {
typename HeuristicFunctorT::result_type value(functor(*it));
if (value > best_value) {
best_value = value;
best = it;
}
}
return best;
}
Note that neither version requires any template arguments, the only requirement is that the heuristic implements the unary_function class
template <typename F>
struct CompareBy
{
bool operator()(const typename F::argument_type& x,
const typename F::argument_type& y)
{ return f(x) < f(y); }
CompareBy(const F& f) : f(f) {}
private:
F f;
};
template <typename T, typename U>
struct Member : std::unary_function<U, T>
{
Member(T U::*ptr) : ptr(ptr) {}
const T& operator()(const U& x) { return x.*ptr; }
private:
T U::*ptr;
};
template <typename F>
CompareBy<F> by(const F& f) { return CompareBy<F>(f); }
template <typename T, typename U>
Member<T, U> mem_ptr(T U::*ptr) { return Member<T, U>(ptr); }
You need to include <functional> for this to work. Now use, from header <algorithm>
std::max_element(v.begin(), v.end(), by(mem_ptr(&A::a)));
or
double combination(A x) { return 0.2 * x.a + 0.8 * x.b; }
and
std::max_element(v.begin(), v.end(), by(std::fun_ptr(combination)));
or even
struct combination : std::unary_function<A, double>
{
combination(double x, double y) : x(x), y(y) {}
double operator()(const A& u) { return x * u.a + y * u.b; }
private:
double x, y;
};
with
std::max_element(v.begin(), v.end(), by(combination(0.2, 0.8)));
to compare by a member or by linear combinations of a and b members. I split the comparer in two because the mem_ptr thing is damn useful and worth being reused. The return value of std::max_element is an iterator to the maximum value. You can dereference it to get the max element, or you can use std::distance(v.begin(), i) to find the corresponding index (include <iterator> first).
See http://codepad.org/XQTx0vql for the complete code.
This is what functors and STL are made for:
// A class whose objects perform custom comparisons
class my_comparator
{
public:
explicit my_comparator(float c1, float c2) : c1(c1), c2(c2) {}
// std::max_element calls this on pairs of elements
bool operator() (const A &x, const A &y) const
{
return (x.a*c1 + x.b*c2) < (y.a*c1 + y.b*c2);
}
private:
const float c1, c2;
};
// Returns the "max" element in vec
*std::max_element(vec.begin(), vec.end(), my_comparator(0.8,0.2));
Is the expression always linear? You could pass in an array of four coefficients. If you need to support arbitrary expressions, you'll need a functor, but if it's just an affine combination of the four fields then there's no need for all that complexity.
You can use the std::max_element algorithm with a custom comparator.
It's easy to write the comparator if your compiler supports lambda expressions.
If it doesn't, you can write a custom comparator functor. For the simple case of just comparing a single member, you can write a generic "member comparator" function object, which would look something like this:
template <typename MemberPointer>
struct member_comparator
{
MemberPointer p_;
member_comparator(MemberPointer p) : p_(p) { }
template <typename T>
bool operator()(const T& lhs, const T& rhs) const
{
return lhs.*p_ < rhs.*p_;
}
};
template <typename MemberPointer>
member_comparator<MemberPointer> make_member_comparator(MemberPointer p)
{
return member_comparator<MemberPointer>(p);
}
used as:
// returns an iterator to the element that has the maximum 'd' member:
std::max_element(v.begin(), v.end(), make_member_comparator(&A::d));
You could use the std::max_element STL algorithm providing a custom comparison predicate each time.
With C++0x you can even use a lambda function for it for maximum conciseness:
auto maxElement=*std::max_element(vector.begin(), vector.end(), [](const A& Left, const A& Right) {
return (0.8*Left.a + 0.2*Left.b)<(0.8*Right.a + 0.2*Right.b);
});
Sample of using max_element/min_element with custom functor
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
struct A{
float a, b, c, d;
};
struct CompareA {
bool operator()(A const & Left, A const & Right) const {
return Left.a < Right.a;
}
};
int main() {
vector<A> vec;
vec.resize(3);
vec[0].a = 1;
vec[1].a = 2;
vec[2].a = 1.5;
vector<A>::iterator it = std::max_element(vec.begin(), vec.end(), CompareA());
cout << "Largest A: " << it->a << endl;
it = std::min_element(vec.begin(), vec.end(), CompareA());
cout << "Smallest A: " << it->a << endl;
}
Is there an stl way to get a list of values from a map?
i.e, I have:
std::map<A,B> myMap;
and I would like a function that will return just the list of values, i.e, std::list<B> (or set for that matter.
Is there a built-in stl way to do this?
A map element is defined as a map::value_type, and the type of it is a pair<A,B>. first is the key and second is the value. You can write a functor to extract second from a value_type, and copy that in to a vector (or a list, or whatever you want.) The best way to do the copying is to use transform, which does just what its name implies: it takes a value of one type and transforms it to a different type of value.
Here's a complete working example:
#include <cstdlib>
#include <map>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;
typedef map<unsigned, string> MyMap;
MyMap my_map;
struct get_second : public std::unary_function<MyMap::value_type, string>
{
string operator()(const MyMap::value_type& value) const
{
return value.second;
}
};
int main()
{
my_map[1] = "one";
my_map[2] = "two";
my_map[3] = "three";
my_map[4] = "four";
my_map[5] = "five";
// get a vector of values
vector<string> my_vals;
transform(my_map.begin(), my_map.end(), back_inserter(my_vals), get_second() );
// dump the list
copy( my_vals.begin(), my_vals.end(), ostream_iterator<string>(cout, "\n"));
}
EDIT:
If you have a compiler that supports C++0x lambdas, you can eliminate the functor entirely. This is very useful for making code more readable and, arguable, easier to maintain since you don't end up with dozens of little one-off functors floating around in your codebase. Here's how you would change the code above to use a lambda:
transform(my_map.begin(), my_map.end(), back_inserter(my_vals), [](const MyMap::value_type& val){return val.second;} );
There's nothing built in, no. It's simple enough to write your own function, though: Iterate over the map. The iterator will give you a pair<A, B>. Add each second value to the result list.
You can't just "get" such a list because there is no pre-existing list stored anywhere in the guts, but you can build one:
typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
for (myMapType::const_iterator it=myMap.begin(); it!=myMap.end(); ++it) {
valueList.push_back( it->second );
}
Or if you really like the more STL way:
class GetSecond {
template<typename T1, typename T2>
const T2& operator()( const std::pair<T1,T2>& key_val ) const
{ return key_val.second; }
};
typedef std::map<A,B> myMapType;
myMapType myMap;
std::list<B> valueList;
std::transform(myMap.begin(), myMap.end(), std::back_inserter(valueList),
GetSecond());
One of many "built-in" ways is of course the most obvious one. Just iterate over all pair elements, which are ordered by key (pair::first), and add the value (pair::second) to a new container, which you can construct with the correct capacity to get rid of excess allocations during the iteration and adding.
Just a note: std::list is seldom the container you actually want to be using. Unless, of course, you really, really do need its specific features.
Sure.
std::list<B> list;
std::for_each(myMap.begin(), myMap.end(), [&](const std::pair<const A, B>& ref) {
list.push_back(ref.second);
});
If you don't have a C++0x compiler, first you have my sympathies, and second, you will need to build a quick function object for this purpose.
You can use boost's transform_iterator: http://www.boost.org/doc/libs/1_64_0/libs/iterator/doc/transform_iterator.html
struct GetSecond {
template <typename K, typename T>
const T& operator()(const std::pair<K, T> & p) const { return p.second; }
template <typename K, typename T>
T& operator()(std::pair<K, T> & p) const { return p.second; }
};
template <typename MapType>
auto begin_values(MapType& m) -> decltype(boost::make_transform_iterator(m.begin(), GetSecond())) {
return boost::make_transform_iterator(m.begin(), GetSecond());
}
template <typename MapType>
auto end_values(MapType& m) -> decltype(boost::make_transform_iterator(m.end(), GetSecond())) {
return boost::make_transform_iterator(m.end(), GetSecond());
}
template <typename MapType>
struct MapValues {
MapType & m;
MapValues(MapType & m) : m(m) {}
typedef decltype(begin_values(m)) iterator;
iterator begin() { return begin_values(m); }
iterator end() { return end_values(m); }
};
template <typename MapType>
MapValues<MapType> get_values(MapType & m) {
return MapValues<MapType>(m);
}
int main() {
std::map<int, double> m;
m[0] = 1.0;
m[10] = 2.0;
for (auto& x : get_values(m)) {
std::cout << x << ',';
x += 1;
}
std::cout << std::endl;
const std::map<int, double> mm = m;
for (auto& x : get_values(mm)) {
std::cout << x << ',';
}
std::cout << std::endl;
}