There is templated vector class(it's about math, not container). I need to overload common math operations. Is there any sense to overload like this:
template <typename T, size_t D> Vector<T, D> operator+(const Vector<T, D>& left, const Vector<T, D>& right) { std::cout << "operator+(&, &)" << std::endl; Vector<T, D> result; for (size_t i = 0; i < D; ++i) result.data[i] = left.data[i] + right.data[i]; return result; } template <typename T, size_t D> Vector<T, D>&& operator+(const Vector<T, D>& left, Vector<T, D>&& right) { std::cout << "operator+(&, &&)" << std::endl; for (size_t i = 0; i < D; ++i) right.data[i] += left.data[i]; return std::move(right); } template <typename T, size_t D> Vector<T, D>&& operator+(Vector<T, D>&& left, const Vector<T, D>& right) { std::cout << "operator+(&&, &)" << std::endl; for (size_t i = 0; i < D; ++i) left.data[i] += right.data[i]; return std::move(left); } This works pretty fine with this test code:
auto v1 = math::Vector<int, 10>(1); auto v2 = math::Vector<int, 10>(7); auto v3 = v1 + v2; printVector(v3); auto v4 = v3 + math::Vector<int, 10>(2); printVector(v4); auto v5 = math::Vector<int, 10>(5) + v4; printVector(v5); // ambiguous overload // auto v6 = math::Vector<int, 10>(100) + math::Vector<int, 10>(99); and prints this:
operator+(&, &) 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, operator+(&, &&) 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, operator+(&&, &) 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, There is problem with two rvalue references, but I think it doesn't matter.
Why I want to do that? Because of performance reason, in theory it would work little bit faster without creating new object, but will it? Maybe compilers optimize simple code with operator +(const Vector& left, const Vector& right) and there is no any reason for overload rvalue?
&&in template function in not the same as&&in a non-template function. In a template function&&is a forwarding reference (and reference collapsing rules apply);&&in a non-template function is a rvalue reference and no collapsing is done. You have forwarding references.foo<T>(as is the case here) it is an actual r-value reference.auto&& result = x + temporary();then the result is a dangling reference since it refers to the temporary that is now dead.