0
votes

I wrote a quick method to convert std::vectors from one type to another:

template<class A, class B>
vector<B> ConvertSTDVector_AToB(vector<A> vector)
{
    vector<B> converted_vector;

    for(unsigned int i= 0; i< vector.size(); i++)
        converted_vector.push_back(vector[i]);

    return converted_vector;
}

But the compiler errors with "error C2275: 'B' : illegal use of this type as an expression" on the line after the opening bracket. At first I thought somehow 'B' was defined elsewhere, but changing both template type names results in the same error. Then I thought that something strange was going on with the types. But even making both template parameters ints doesn't change anything.

I can't for the life of me see what's wrong with this method. (Although I feel like I might just be blind to something obvious, at this point).

2
This redefines the meaning of vector: vector<A> vector. Instead of naming a type, it names a function parameter. Replace with vector<A> v, and the code should compile (demo).Sergey Kalinichenko
So you're intentionally reinventing std::transform ?WhozCraig
@WhozCraig or std::copy :).101010
@WhozCraig More like std::copy without explicit conversion?pmr
@pmr I think half the standard lib algorithms could be tooled to do this, now that a I think about it more. I like Brian's =PWhozCraig

2 Answers

4
votes

Simply rename the parameter name. Its name hides the std::vector name.

Or write the erroneous line the following way

class vector<B> converted_vector;

that is use the elaborated type name for std::vector that to distinguish it from object (parameter) vector.

The code of the function can be written in different ways. For example

template<class A, class B>
vector<B> ConvertSTDVector_AToB(vector<A> vector)
{
    class vector<B> converted_vector( vector.begin(), vector.end() );

    return converted_vector;
}

pr

template<class A, class B>
vector<B> ConvertSTDVector_AToB(vector<A> vector)
{
    class vector<B> converted_vector;

    converted_vector.assign( vector.begin(), vector.end() );
    return converted_vector;
}

ans so on.

1
votes

You don't really have to do such a function, instead all you have to do is to use std::copy provided that the objects you want to convert are convertible to each other by providing an overloaded conversion operator. Just like the example below:

#include <vector>
#include <iostream>
#include <algorithm>

class B;

class A {
  friend std::ostream& operator<<(std::ostream &out, A const &a);
  int id;
public:
  A() : id(0) { }
  A(int const _id) : id(_id) { }
  operator B() const; 
};

class B {
  friend std::ostream& operator<<(std::ostream &out, B const &b);
  int id;
public:
  B() : id(0) { }
  B(int const _id) : id(_id) { }
  operator A() const { return A(id); }
};

A::operator B() const { return B(id); }

std::ostream& operator<<(std::ostream &out, A const &a) { return (out << a.id); }
std::ostream& operator<<(std::ostream &out, B const &b) { return (out << b.id); }

int main() {
  std::vector<B> bv{B(1), B(2), B(3), B(4), B(5)};
  std::vector<A> av(bv.size());
  std::vector<B> bbv(bv.size());
  std::copy(bv.begin(), bv.end(), av.begin());
  for(auto i : av) std::cout << i << " ";
  std::cout << std::endl;
  std::copy(av.begin(), av.end(), bbv.begin());
  for(auto i : bbv) std::cout << i << " ";
  std::cout << std::endl;  
  return 0;
}

DEMO