Tomasz Szulc
Tomasz Szulc

Reputation: 4235

Cannot pass vector of subclass when base class required as a param

I have a class A and its subclass B and a method that takes std::vector<A>. And I cannot make it work by passing std::vector<B>.

I though that if subclass B can be casted to A, I should be able to pass vector of Bs to method that takes vector of As. How can I do that properly?

#include <iostream>
#include <vector>

class A {

    public:

        A() {}
};

class B: public A {

    public: 

        B(): A() {}
};

void method(std::vector<A> a) {}

int main() {
    std::vector<B> b;
    method(b);

    return 0;
}

When compiled:

g++ ex-cast-tag.cpp -std=c++11

ex-cast-tag.cpp:22:5: error: no matching function for call to 'method'
    method(b);
    ^~~~~~
ex-cast-tag.cpp:18:6: note: candidate function not viable: no known conversion from 'vector<B>' to 'vector<A>'
  for 1st argument
void method(std::vector<A> a) {}
     ^
1 error generated.

Thanks in advance!

Upvotes: 0

Views: 796

Answers (2)

Walter
Walter

Reputation: 45414

One solution is to use a template. For example

template<typename C>
std::enable_if_t<std::is_base_of<A,C>::value>
method(std::vector<C> const&a) 
{
    // assume that a[i] is an A (derived or actually the same)

}

Here, I have used SFINAE to ensure that C is actually A or derived from A. But you can also use static_assert instead. In this case you get nicer error messages, but the overloading behaviour of method() is different (i.e. when this template is considered).

Upvotes: 3

Code-Apprentice
Code-Apprentice

Reputation: 83517

If B is a subclass of A, it does not follow that std::vector<B> is a subclass of std::vector<A>. In order to use inheritance correctly here, you need to change the function to accept a parameter of type std::vector<A*> then pass it a std::vector<A*> whose pointers all point to instances of type B. Alternatively, you can make the function into a template function.

Upvotes: 1

Related Questions