Consider this example:
#include <memory>
template<typename T>
class A {};
template<typename T1, typename T2>
class B: public A<T1> {};
template<typename T = int>
void foo(std::shared_ptr< A<T> > test)
{
}
int main()
{
auto p = std::make_shared<B<int, int>>();
foo<int>(p); // Works
foo<>(p); // Does not work
foo(p); // Does not work
}
I'm trying to get this to compile without explicitly specifying the type T for foo, but it doesn't work. I'm not sure why as if I explicitly the type T, it works just fine, but if I it, it doesn't compile, even though I've told the compiler the what the type T should be if I don't explicitly specify it.
I get why the compiler can't deduce the type T, but why can't it use my default type T when I don't specify it? How do I get around this and what is the "proper" way of doing this?
The problem isn't related to the default template parameter. Instead, the type of p
(std::shared_ptr<B<int, int>>
) can't be matched against the std::shared_ptr<T>
argument of the template foo
: During template argument deduction, no conversions are taken into account, and passing a reference to a derived class instance as a base class reference is indeed a conversion.
You can fix the issue by explicitly upcasting the pointer that std::shared_ptr
manages.
std::shared_ptr<A<int>> p = std::make_shared<B<int, int>>();
Now, these calls will work out as expected:
foo<>(p); // Ok, argument matches the signature
foo(p); // Same...
Note that it makes a big difference whether the template argument type appears in the parameter list of a function template (making deduction possible) or not. Consider these two templates,
template <class T = int> void foo(T&&)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
template <class T = int> void bar(double)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
Both have the default type int
, but when they are instantiated like this
foo<>(0.0); // outputs: void foo(T&&) [with T = double]
bar<>(0.0); // outputs: void bar(double) [with T = int]
the first instantiation uses the function argument to deduce the template parameter (results in double
), while the second doesn't deduce anything and defaults to int
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With