-1

I want to pass the a vector filled with object based same class. Both std::reference_wrapper and no-reference do not fix it. What's the correct way to solve this?

class MyClass
{
public:
    MyClass(int){};
    virtual void print() const {
        std::cout<<"MyClass"<<std::endl;
    }
};
class MySubClass : public MyClass
{
public:
    MySubClass(int a):MyClass(a){};
    virtual void print() const {
        std::cout<<"MySubClass"<<std::endl;
    }
};
void test(const std::vector<std::reference_wrapper<MyClass>>& v)
{
    for (const auto& c : v) {
        c.get().print();
    }
}
void test(const std::vector<MyClass>& v)
{
    for (const auto& c : v) {
        c.print();
    }
}
int main() 
{
    {
        MySubClass s(2);
        std::vector<MyClass> v;
        v.push_back(s);
        test(v);//print MyClass, but I need MySubClass
    }
    {
        MySubClass s(2);
        std::vector<std::reference_wrapper<MyClass>> v;
        v.push_back(s);
        test(v);//print MySubClass
        test({2});
        test({s});//wrong ambigious
    }
    return 0;
}
Ringo_D
  • 784
  • 5
  • 18
  • 2
    `const std::vector& v` - There is no copy of `MyClass` here since you are passing a reference to the vector. – Holt Jan 04 '17 at 06:59
  • 6
    You're comparing apples to motorbikes -- do you want a vector of references or a vector of objects? They have completely different uses. What are you trying to do? – Chris Dodd Jan 04 '17 at 07:02
  • @Holt Sorry, I didn't make it clear enough. Now I re-edited. – Ringo_D Jan 04 '17 at 07:35
  • @ChrisDodd Sorry, I didn't make it clear enough. Now I re-edited. – Ringo_D Jan 04 '17 at 07:35

1 Answers1

1
{
    MySubClass s(2);
    std::vector<MyClass> v;
    v.push_back(s);
    test(v);//print MyClass, but I need MySubClass
}

The problem here is that you're attempting to store MySubClass objects in a vector of MyClass. It is not possible to store the entire MySubClass, instead only the MyClass parent subobject is stored. This conflicts with your desire to treat the stored objects as if they were MySubClass instances.

{
    MySubClass s(2);
    std::vector<std::reference_wrapper<MyClass>> v;
    v.push_back(s);

This solves the previous problem. References can refer to a subclass of their static type. Although, keep in mind that the object is not stored in the vector. The object is stored as a local variable s and only referenced by the vector.

    test(v);//print MySubClass
    test({2});
    test({s});//wrong ambigious

The problem here is that you have two overloads, of which neither accept a MySubClass, but both accept something that can be initialized from an initialization list of MySubClass. Therefore the overload resolution is abiguous. The compiler doesn't know which overload you intended to call.

Either use explicit temporary initialization instead of a plain initializion list.

    test(std::vector<MyClass>{2});
    test(std::vector<std::reference_wrapper<MyClass>>{s});

Or don't use overloads, but uniquely named functions instead.

void test(const std::vector<std::reference_wrapper<MyClass>>& v)
void test2(const std::vector<MyClass>& v)
eerorika
  • 232,697
  • 12
  • 197
  • 326