Add operator<< to std::vector

2019-07-07 05:39发布

问题:

I want to add operator<< to std::vector<string>. This is the operator

std::vector<std::string>& operator<<(std::vector<std::string>& op, std::string str) {
    op.push_back(str);
    return op;
}

Now I can add elements to vector this way:

std::vector<std::string> vec;
vec << "aaa" << "bbb" << "ccc";

But the following code isn’t compiled since cant pass temporary object by reference.

std::vector<std::string>() << "AAA" << "BBB";

How can I change the code to add elements to temporary vectors too?

I have a function which accepts const std::vector<std::string>& argument so I want to pass to it a vector in one line.

回答1:

You can't. The only way it could be achieved would be if your operator was a member of the vector. (For some reason member functions can be invoked on temporaries).

As a nonmember function though what you're after is impossible

Also it's not a very good idea to overload operators for STL types such as std::vector. I think what you're trying to accomplish is already present in boost assign library. I don't believe you can write it better than they have, so better use boost if you need this.



回答2:

I haven't actually thought about the consequences of this properly, but it seems you could have an overload for rvalues:

std::vector<std::string> operator<<(std::vector<std::string>&& op, std::string str) {
  op.push_back(std::move(str));
  return op;
}

Yes, it returns by value, but it will be optimized to a move due to §12.8/32:

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.



回答3:

Well... technically it is doable but in dirty style. Just for illustration (I'm not so sure it worth real implementation). Checked to work with GCC 4.7.2. I really don't know how this will behave on constant objects.

#include <vector>
#include <string>
#include <iostream>

const std::vector<std::string>& operator << (const std::vector<std::string>& op, const std::string &str) 
{
    ((std::vector<std::string>&) op).push_back(str);
    return op;
}

int main()
{
    std::vector<std::string> a = std::vector<std::string>() << "A" << "B";
    a << "AAA";

    std::cout << "size: " << a.size() << std::endl;
    for (std::vector<std::string>::iterator i = a.begin(); i != a.end(); ++i)
    {
        std::cout << '\t' << *i << std::endl;
    }

    return 0;
}


回答4:

This is a code, that helps you to do something similar to your idea (http://ideone.com/3lrTxW):

#include <vector>
#include <string>

typedef std::string String;
typedef std::vector<String> StringVector;

class StringVectorWrapper {
    StringVector vector;
public:    
    operator StringVector&() {
        return vector;        
    }

    StringVectorWrapper& operator << (const String& str) {
        vector.push_back(str);
        return *this;
    }
};

And an example of use:

#include <iostream>    

void printVector(const StringVector& vector) {
    for(StringVector::const_iterator it = vector.begin(); it != vector.end(); it++)
        std::cout << *it << std::endl;
}

int main(void) {

    StringVectorWrapper w;
    w << "A" << "B";    
    printVector(w);

    printVector(StringVectorWrapper() << "Z" << "W");


    return 0;
}

But I would not use such a code in any of my programs.



回答5:

I'm afraid this is not possible. Also it's a bad idea to overload operator for any standard library class. The STL is not meant to be extended.



标签: c++ vector