Here I declared two template classes: A and B, B derives from A:
template<typename T>
class A {
public:
int a;
T t;
};
template<typename T>
class B : public A<T> {
public:
int b;
};
And I make a shared_ptr<B<T>>
and assign it to shared_ptr<A<T>>
, it's ok:
auto b = std::make_shared<B<std::string>>();
std::shared_ptr<A<std::string>> a = b;
Here I declared a template function accept shared_ptr A<T>
:
template<typename T>
void proc(std::shared_ptr<A<T>> &a) {
std::cout << a->a << std::endl;
}
it accepts a
as argument, but rejects b
:
proc<std::string>(a); // OK
proc<std::string>(b); // template argument deduction/substitution failed
// cannot convert 'b' (type 'std::shared_ptr<B<std::__cxx11::basic_string<char> > >') to type 'std::shared_ptr<A<std::__cxx11::basic_string<char> > >&'
I use g++ as compiler with -std=c++11.
This error brings me a lot problems and how could I fix this elegantly?
Given proc<std::string>(b);
, b
needs to be converted to std::shared_ptr<A<std::string>>
. That means a temporary std::shared_ptr<A<std::string>>
will be constructed and then passed to proc
. The parameter type of proc
is an lvalue-reference to non-const, i.e. std::shared_ptr<A<T>> &
, which can't bind to temporaries.
You can change the parameter type to lvalue-reference to const, which could bind to temporaries. e.g.
template<typename T>
void proc(const std::shared_ptr<A<T>> &a) {
// ^^^^^
std::cout << a->a << std::endl;
}