简体   繁体   中英

Overload operator + for vector: namespace std

I am trying to overload the operator + and += for std::vector, and what I do is

namespace std {
    template<class T>
    vector<T> operator+(vector<T> x, vector<T> y) {
        vector<T> result;
        result.reserve(x.size());
        for (size_t i = 0; i < x.size(); i++)
            result[i] = x[i] + y[i];
        return result;
   }
}

But I assume this is bad practice, because clang-tidy warns me "Modification of std namespace can result in undefined behavior". Is there other better practice in overloading operator for STL classes?

Best practice is not to do it.

But if you really want to you still can: just don't put it in namespace std .

And don't take your arguments by value, unless you're deliberately doing so in order to make the most of move semantics (which you're not).

I suggest:

  1. Don't overload the operators. Create regular functions instead.
  2. Put the functions in a namespace specific to your app.

Example:

namespace MyApp
{
   template <typename T>
   std::vector add(std::vector<T> const& lhs, std::vector<T> const& rhs) { ... }

   template <typename T>
   std::vector& append(std::vector<T>& lhs, std::vector<T> const& rhs) { ... }
}

Inserting functions into std makes your program ill formed, no diagnostic required.

In certain limited circumstances you may insert specializations into std , but that cannot do what you want here.

So you cannot insert vec + vec into std .

Putting an operator in a different namespace is legal, but ill-advised. Operators do not work well when they cannot be found via ADL/Koenig lookup. Code that is seemingly reasonable, like std::accumulate( vec_of_vec.begin(), vec_of_vec.end(), std::vector<int>{} ) fails to compile, among other issues.

The short answer is, vector isn't your type. Don't do this.

You can create helper functions elsewhere, like util::elementwise_add( vec, vec ) .

The std did not implement + because both concatination and elementwise operations where reasonable. valarray does implement elementwise operations; possibly what you want is std::valarray<int> instead of std::vector<int> .

Failing all of this, you could write a named operator vec +by_elem+ vec or inherit from std::vector in your own namespace, use that type, and overload + for your type. (Inheriting from std::vector is pretty safe; so long as nobody plays with heap allocated raw pointers to std::vector s or similar)

Whether you implement addition as operator+(...) or as a function add(...) , you'd better do it this way:

template<class T>
std::vector<T> operator+(std::vector<T> x, const std::vector<T>& y) {
    assert(x.size() == y.size());
    for (std::size_t i = 0; i < x.size(); ++i)
        x[i] += y[i];
    return x;
}

By taking the first vector by value (and not by const-ref) you'll force a compiler to make a copy for you automatically to hold the result.

Addition after reading this comment .

Due to left-to-right associativity of + , an expression like a + b + c is parsed as (a + b) + c . Hence, if the first (and not the second) argument in operator+(... x, ... y) is taken by value, the prvalue returned by a + b can be moved into x . Otherwise, unnecessary copies will be made.

You may should create your own vector class inherits from std::vector and define the new operator

#include <iostream>
#include <vector>

template<class T>
class MyVec : public std::vector<T>
{
public:
    MyVec& operator+=(const T& add)
    {
        reserve(1);
        push_back(add);
        return *this;
    }
};

int main()
{
    MyVec<int> vec;
    vec += 5;
    vec += 10;

    for (auto& e : vec)
    {
        std::cout << e << "\t";
    }

    std::cin.get();
}

Edit : sry i did not know that this solution causes undefined behaviour. Then i would suggest a similar solution shown in the post above. But why do you need the plus operator? Isnt push_back good enough? You could implement a reference return value to continue the addition. So you can do things like that:

vec + 20 + 30;

to add two elements (20 and 30). This is less code but is is more readable?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM