Arithmetic operations on vectors

Say I want to provide element-wise arithmetic operations operator+= and operator+ for std::vector to add vector entries element by element. Often, I see operator+ being implemented in terms of operator+= like so:

#include <algorithm>
#include <vector>

template<class Type>
std::vector<Type> & operator+=(std::vector<Type> &x, const std::vector<Type> &y) {
    // Checks for equal size of x and y omitted here...
    std::transform(std::begin(x), std::end(x), std::begin(y), std::begin(x), std::plus<Type>());
    return x;
}

template<class Type>
std::vector<Type> operator+(std::vector<Type> x, const std::vector<Type> &y) {
    // Checks for equal size of x and y omitted here...
    return x += y;
}

int main() {
    std::vector<double> v0{1.0, 2.0, 3.0};
    auto v1 = v0;

    auto v2 = v0;
    v2 += v0; // yields [2, 4, 6]

    auto v3 = v0 + v1; // yields [2, 4, 6]

    return 0;
}

In terms of performance, I guess

template<class Type>
std::vector<Type> operator+(const std::vector<Type> &x, const std::vector<Type> &y) {
    // Checks for equal size of x and y omitted here...
    std::vector<Type> result;
    result.reserve(x.size());
    std::transform(std::begin(x), std::end(x), std::begin(y), std::back_inserter(result), std::plus<Type>());
    return result;
}

is more efficient because it avoids initializing the copy of the first argument when entering the function but places the result directly into an uninitialized chunk of memory. Is it really worth it to implement the second version or can I assume the compiler to optimize anyway? Also, I consider the second alternative less generic than the first one. Imagine something like

#include <array>
#include <type_traits>

template<class Container, class Enable = void>
struct IsSequenceContainer: public std::false_type {
};

template<>
template<class Type, std::size_t size>
struct IsSequenceContainer<std::array<Type, size> >: public std::true_type {
};

template<>
template<class Type, class Allocator>
struct IsSequenceContainer<std::vector<Type, Allocator> >: public std::true_type {
};

// Use the following operations for std::array and std::vector
template<class Container>
typename std::enable_if<IsSequenceContainer<Container>::value, Container>::type operator+(Container x, const Container &y) {
    return x += y;
}

Answers


As with everything performance related: Profile the program, to see the what happens.

My guess is that the compiler will not optimize the code fully - and that it will probably never matter. The only way to know for sure is to try it out.

Implementing + in terms of += has the advantage that the two operations are known to be equivalent. This makes it less likely for a bug to occur. You should make sure that your optimization is necessary, before you give up this advantage. The idioms of C++ have usually become idioms for good reasons.


Have you had a look at std::valarray? It already provides those operation you need and you might benefit from SIMD. Which might be a performance++ for free.


Need Your Help

Although there is a data row, resultset is empty

java mysql spring amazon-web-services ibatis

First of all, I'd like to explain the development environment and what I have done so far.

Configure openHAB to run over USB with KNX

ubuntu openhab knx

I have some problems to establish a connection to my KNX over USB. There is no problem to run the demo-project or even my project.