Sinapse
Sinapse

Reputation: 792

automatic conversion between stl vectors

What I want is to copy an std::vector<int> to another std::vector<myStruct> with assignment operator in which myStruct can be assigned an int. So I wrote this piece of code:

#include <vector>
#include <iostream>

using namespace std;

struct myStruct
{
   myStruct(int& a) : _val(a) { }
   myStruct(int&& a) : _val(a) { }

   myStruct& operator=(int& a)
   {
      _val = a;
      return *this;
   }

   int _val;
};

int main()
{
   vector<int> ivec;
   ivec.push_back(1);
   vector<myStruct> svec = ivec;

   return 0;
}

And it gives me error as it cannot find a valid conversion between std::vector<myStruct> and std::vector<int> although int can implicitly be converted to myStruct. On the other hand, assign operator cannot be declared outside the class so I deduce writing an operator manually is not an option. So what should I do in this situation?

*** UPDATE: As Blastfurnace and others said this can be solved using this code instead of assignment:

vector<myStruct> svec(ivec.begin(), ivec.end());

But imagine the situation in which I want to write a library and want to handle this in the library itself so the user can just write std::vector<myStruct> svec = someFunction() in which someFunction returns std::vector<int>. Isn't there any solution for this?

Upvotes: 4

Views: 95

Answers (3)

CoffeDeveloper
CoffeDeveloper

Reputation: 8325

Your best bet is having a conversion function

std::vector< myStruct> convertVector( const std::vector< int> & other)
{
    return std::vector< myStruct> ( ivec.begin(), ivec.end() );
}

that would automatically use return value optimization so no overhead for copying the data twice (you just copy data once instead when you iterate the "other" vector).


Just for the sake of completeness:

By using custom datatypes it is possible adding custom type conversion but I guess that's generally a bad Idea and you may not be interested in, anyway:

class IntVector: public std::vector<int>{
    public:
    //conversion operator (note a VERY BAD IDEA using this, may come in handy in few cases)
    operator myStructVector () { 
        return convertVector(*this); 
    }
}

class myStructVector: public std::vector< myStruct>{
    //....
};

usage:

int main()
{
    IntVector ivec;
    ivec.push_back(1);
    myStructVector svec = (myStructVector)ivec;

    return 0;
}

I would discourage going this way anyway ^^

Upvotes: 1

Rostislav
Rostislav

Reputation: 3977

You can use vector<myStruct> svec(ivec.begin(), ivec.end()); instead.

You could also use std::copy(ivec.begin(), ivec.end(), std::back_inserter(svec)); or svec.assign(ivec.begin(), ivec.end()); as it might be better in case you assign multiple times as it can reuse the capacity of the vector<myStruct> after it was cleared.

Upvotes: 4

Blastfurnace
Blastfurnace

Reputation: 18652

You could use the constructor overload that takes an iterator range:

vector<myStruct> svec(ivec.begin(), ivec.end());

Upvotes: 5

Related Questions