4

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;
}
5
  • Be careful if you provide element-wise addition for vectors - be sure that operator+ isn't mistaken for a concatenation operator... Commented Dec 2, 2015 at 9:20
  • There's also std::valarray, but it doesn't support erase, insert etc. Commented Dec 2, 2015 at 9:26
  • @melak47 I am aware of std::valarray but I would actually prefer std::vector over std::valarray, see this post, for example. Commented Dec 2, 2015 at 9:44
  • @TobySpeight I am aware of the ambiguity of operator+= and operator+ with regard to containers. However, IMHO, as long as you clearly document your intent and depending on your application (e.g., scientific applications), it is perfectly legal to provide such operators, which might have a different meaning in a different context. Commented Dec 2, 2015 at 9:47
  • 1
    Adding operator overloads for standard containers is problematic. It won't be found by ADL (since that only looks up namespace std;); and if you are in another with any definition of operator+= , it will hide this one. Commented Dec 2, 2015 at 10:26

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.