468,456 Members | 1,663 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,456 developers. It's quick & easy.

Template argument deduction and conversion operators.

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
3 1690
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
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
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.

Similar topics

7 posts views Thread by bartek | last post: by
4 posts views Thread by Dave | last post: by
5 posts views Thread by Steven T. Hatton | last post: by
14 posts views Thread by Bart Samwel | last post: by
5 posts views Thread by Vijai Kalyan | last post: by
2 posts views Thread by coolpint | last post: by
3 posts views Thread by =?gb2312?B?wfXquw==?= | last post: by
reply views Thread by NPC403 | last post: by
1 post views Thread by subhajit12345 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.