Overload operator + for vector: namespace std

ぐ巨炮叔叔 提交于 2021-01-29 15:57:01

问题


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?


回答1:


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).




回答2:


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) { ... }
}



回答3:


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::vectors or similar)




回答4:


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.




回答5:


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?



来源:https://stackoverflow.com/questions/52103950/overload-operator-for-vector-namespace-std

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!