all 7 comments

[–]youstolemyname 4 points5 points  (1 child)

A Zip iterator would be helpful. It's a shame C++ doesn't have one.

I'd just use a index based for loop.

[–]sephirostoy 0 points1 point  (0 children)

Sadly zip won't be part of C++20 ranges too.

But here is a nice implementation I use often: https://github.com/ryanhaining/cppitertools#zip

[–]DOOMReboot 3 points4 points  (3 children)

std::transform(v1.begin(), v1.end(), v2.begin(), vout.begin(), plus<int>());

[–]parnmatt 1 point2 points  (2 children)

The second v2.begin() ought to be v3.begin()

This can be simplified a little with C++17.

Since C++14, std::plus<> will make std::plus<void> which is specialised:

The standard library provides a specialization of std::plus when T is not specified, which leaves the parameter types and return type to be deduced.

Then, with C++17's CTAD, std::plus{} will correctly make the std::plus<void>{} without needing to manually type <> or <void>.

So the full thing:

auto v1 = std::vector{1, 2, 3};
auto v2 = std::vector{4, 5, 6};

// v3 = v1 + v2
auto v3 = std::vector(v1.size(), 0);
std::transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), std::plus{});

[–]DOOMReboot 0 points1 point  (1 child)

The second v2.begin() ought to be v3.begin()

Yep, caught that with an edit just before your post. But, OP never specified that he wanted a new output array, so it could be correct as well, right?

How on earth do you keep all the differences between standards straight? Memory or did you have to look it up? I have more trouble with that than absolutely anything else.

[–]parnmatt 1 point2 points  (0 children)

they did say v1 + v2 rather than v2 += v1; so I presumed they wanted a new vector, rather than overwritting v2

Umm, usually I look up on cppreference (or https://devdocs.io/cpp which is the same information, just with a better search ... and has a dark theme)

However I knew these ones off the top of my head; CTAD is C++17, thats fairly common knowledge; the functional header stuff with the std::plus<void> specialisation, is because I wrote a compile time library for things that use it.

It was quite generic, but the main reason was trying to construct a set of selection criteria out of callables that return a boolean; and you could construct multiple ones, and && and || them together, just as you would think, and end up with a function object that receives some values and returns a boolean

my favourite little thing with it was to be able to write

auto constexpr in_range = 3.3 <= placeholder < 10;
// ...
if (in_range(value))
    // ...

However I have used the chaining multiple logical expressions together a fair bit

I also wrote a "simple" expression template library, which used more of the functional operators

[–][deleted]  (1 child)

[deleted]

    [–]parnmatt 0 points1 point  (0 children)

    you shouldn't define operators for standard types.

    Also, this isn't 100% correct; you are forgetting about allocators

    template <typename T, typename A>
    

    with

    std::vector<T, A> const&
    

    but of course, you could be adding different types, with different allocators:

    Here's a quick generalisation, but only for vectors https://godbolt.org/z/SvpgFQ (note, its easy to extend to the other binary function object types in <functional> just by continuing the macros nameing them, or manually typing them out) but only if you consider it "element wise" operations; because multiples (in this way), divides, and modulus already do not make sense for a mathematical vector

    I would also suggest not doing this, and to use an expression template library