Here is an example of a code that works perfectly:
#include
#include
template< class D, template< class D, class A >
template argument deduction is pattern matching. It does not do much conversion of the arguments other than conversion-to-base (well, adding const
and reference qualifiers on the type and decay
).
While nullptr
can be converted into a C< D, A >*
, it is not such a type. And both arguments participate equally in the deduction.
You can block deduction of the second argument by using something like typename std::identity
, and the same for the first argument. If you do it for both arguments, the template
types will not be deduced.
Another approach would be to take two arbitrary types, then use SFINAE to ensure that one type of pointer can be converted to the other, and the one that can be can be converted to from the other can be deduced to be a C
for some template
C
and types D
and A
. This probably matches what your internal mental model of what the function type deduction should do. However, the result will be really, really verbose.
An even better approach might be asking "what do you expect to do with these two arguments", and do duck-type testing on that, rather than doing type matching.