By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,171 Members | 930 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,171 IT Pros & Developers. It's quick & easy.

Template argument deduction and conversion operators.

P: n/a
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.

Jul 23 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Bi****@abv.bg wrote:
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.


No. The rule is that the conversions are not applied when trying to
deduce template arguments. There are several (although quite a few)
context in which the argument is deducible, and none of them involve
conversions, IIRC.

V
Jul 23 '05 #2

P: n/a
Bi****@abv.bg wrote:
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'.

--
Best regards,
Andrey Tarasevich
Jul 23 '05 #3

P: n/a
Yes, you are right that in the case with auto_ptr and auto_ptr_ref the
call is ambiguous! And all this is due to the templated conversion
operator.
Now, could you consider my previous question in the case where the
conversion operator is not templated as in the code that follows. My
question was: is it possible to deduce templat*e arguments in a way
that will allow conversion operators to be called i*f necessary?

template< typename SomeType >
class RW;

template< typename SomeType >
class RWRef
{
private:
RWRef( RW< SomeType > const* const ){ }
friend RW< SomeType >;
};

template< typename SomeType >
class RW
{
public:
RW( ) { }

operator RWRef< SomeType >( ) const { return RWRef< SomeType >( this
); }
};

template< typename SomeType >
void f
(
RWRef< SomeType >
)
{
}

int main
(
int,
char*[]
)
{
RW< int > a;
f( a );

return 0;
}

Jul 23 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.