Templates & automatic type conversion

S

Szabolcs

Consider the attached example. When I try to compile it (with g++
4.1.2), I get the error message

error: no matching function for call to 'fun(A<int>&)'

However, if I do not use templates, it compiles without errors.

Could someone please explain why this happens? Is there a workaround?

------------->8---------------

// With A and B templates

template<typename T>
struct B { };

template<typename T>
struct A {
operator B<T> () { return B<T>(); }
};

template<typename T>
void fun(B<T> b) { }

int main() {
A<int> a;
fun(a);
return 0;
}

------------->8---------------

// Without templates

struct B { };

struct A {
operator B() { return B(); }
};

void fun(B b) { }

int main() {
A a;
fun(a);
return 0;
}
 
S

Szabolcs

Szabolcs said:
Consider the attached example. When I try to compile it (with g++
4.1.2), I get the error message

error: no matching function for call to 'fun(A<int>&)'

However, if I do not use templates, it compiles without errors.

Could someone please explain why this happens? Is there a workaround?

------------->8---------------

// With A and B templates

template<typename T>
struct B { };

template<typename T>
struct A {
operator B<T> () { return B<T>(); }
};

template<typename T>
void fun(B<T> b) { }

int main() {
A<int> a;
fun(a);
return 0;
}

------------->8---------------

// Without templates

struct B { };

struct A {
operator B() { return B(); }
};

void fun(B b) { }

int main() {
A a;
fun(a);
return 0;
}

I would like to mention that even if the conversion path is provided
through a constructor of B, like

template<typename T>
struct B { B(A<T> &) {} }

implicit conversion does not work unless the function fun(B b) is not a
template. So is there no way of making implicit conversion work in
function templates?

To explain my motivation for doing this: I need to create the const and
non-const versions of a class separately, because, for certain reasons,
using the const qualifier does not work in this case. The non-const
version should be implicitly converted to the const version whenever
necessary.
 
J

James Kanze

Consider the attached example. When I try to compile it (with g++
4.1.2), I get the error message
error: no matching function for call to 'fun(A<int>&)'
However, if I do not use templates, it compiles without errors.
Could someone please explain why this happens?
------------->8---------------
// With A and B templates
template<typename T>
struct B { };
template<typename T>
struct A {
operator B<T> () { return B<T>(); }
};
template<typename T>
void fun(B<T> b) { }
int main() {
A<int> a;
fun(a);

Here, there is no function fun, only a function template. The
compiler procedes by trying to do type resolution on the
template. It needs a function with a signature "fun(A<int>)";
it can get by with "fun(A<int>&)", or "fun(A<int> const&)", but
that's about it. So type deduction fails, the function overload
set is empty, and overload resolution complains that it cannot
find a match.
return 0;
}

// Without templates
struct B { };
struct A {
operator B() { return B(); }
};
void fun(B b) { }
int main() {
A a;
fun(a);

Here, the compiler has a function, "fun(B)", to add to the
overload set, without any need to do type deduction or
instantiate a template. Since it is the only function in the
overload set (and it can be called), it is the unique best
match.
return 0;

}
Is there a workaround?

You've found it: don't use templates:).

Seriously, if you want complex, user defined conversions to be
considered, you might try offering a second template:

template< typename T >
void
fun( B< T > b )
{
fun( static_cast< A< T > >( b ) ;
}
 
G

Gianni Mariani

Szabolcs said:
Consider the attached example. When I try to compile it (with g++
4.1.2), I get the error message

error: no matching function for call to 'fun(A<int>&)'

However, if I do not use templates, it compiles without errors.

Could someone please explain why this happens? Is there a workaround?

------------->8---------------

// With A and B templates

template<typename T>
struct B { };

template<typename T>
struct A {
operator B<T> () { return B<T>(); }
};

template<typename T>
void fun(B<T> b) { }

int main() {
A<int> a;
fun(a);
return 0;
}

perhaps you can overload fun

template<typename T>
void fun(A<T> & b) { }

perhaps you can be explicit

fun<int>(a)

perhaps you can open up fun for any type

template<typename T>
void fun(T & b) { }
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top