Here is a piece of code:
#include <memory>
using namespace std;
template< typename SomeType >
void f(auto_ptr_ref< SomeType >)
{
}
int __cdecl main(int,char*[])
{
auto_ptr< int > a;
f( a ); // 1: could not deduce template argument
f< int >( a ); // 2: OK
return 0;
}
My question is if there is a standard way to force the compiler to
compile line 1 as it compiles line 2, i.e. to deduce template arguments
in a way that will allow conversion operators to be called if
necessary.
Of course not. We can even forget about the rules of template argument
deduction. It is impossible for a more generic reason.
The conversion operator that converts 'auto_ptr<T>' to
'auto_ptr<T>::auto_ptr_ref<U>' is itself a template with its own
independent parameter (note 'U'). This means that the above conversion
is infinitely ambiguous. How do you expect the compiler to treat the
line 1? As
f<int>(a.operator auto_ptr_ref<int>());
? Why not
f<double>(a.operator auto_ptr_ref<double>());
or
f<char>(a.operator auto_ptr_ref<char>());
Note, once again, that the parameter of the conversion operator template
is not related in any way to the parameter of the entire 'auto_ptr<>'
class template, which means that from the compiler's point of view the
first variant (with 'int') is in no way better than any other variant.
(It's like solving an equation with two unknowns. In general case it has
infinite number of solutions and no one is better than the others.)
In order to resolve the ambiguity in one way of another you have to
provide compiler with extra information. On way to do it is to specify
the 'f' template argument explicitly and let the compiler to deduce the
argument for the conversion operator
f<int>(a);
Another way would be to perform explicit type conversion and let the
compiler to deduce 'f's template argument
f((auto_ptr<int>::auto_ptr_ref<int>) a);
The last example is provided for purely illustrational purposes, it will
not work in practice because 'auto_ptr_ref' is not a public member of
'auto_ptr'.