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;
}
Aucun commentaire:
Enregistrer un commentaire