Templates & Implicit Casting

B

Brian Byrne

I've recently developed a minor interest in Expression Templates and,
in attempt to further my understanding of template metaprogramming,
have been trying to create my own implementation. It seems I've ran
into a problem that, while there are ways around it (causing way for
code duplication), I'm not too sure if a direct solution exists. Given:

template< typename T >
class A { ... };

template< typename T >
void Foo( const A< T >& a ) { ... }

class B { ... };
class C { ... };

Here, I can call Foo directly just fine:

A< B > ab;
Foo( ab );

But suppose I wanted to be able to pass a built-in type to Foo. For
example, a float, and have it IMPLICITLY (key!) be converted to a type
A< C >. Then I could do the following without problem:

float f = 5.0f;
Foo( f ); // ideally implicitly casted to: Foo( A< C >( 5.0f ) );

To get this implicit cast, I figured I could specialize A; something
along the lines of:

template<>
class A< C > {
...
public: A( float f ) { ... }
};

Now A< C > has a non-explicit constructor taking a float, and if C is
the only class used as a template parameter for A, then I had hoped the
compiler could unambiguously do the cast. Unfortunately, the compiler
looked right over it.

So, is it possible?

Any help appreciated!
-- Brian Byrne
 
G

Gianni Mariani

Brian said:
So, is it possible?

Perhaps. Does this do what you want it to do ?


template< typename T >
class A { };

template< typename T >
void Foo( T )
{
char INVALID_FUNCTION[ sizeof( T ) * -1 ];
}

template< typename T >
void Foo( const A< T >& a )
{
}

class B { };
class C { };

template<>
class A< C > {
public: A( float f ) {}
};

template< >
void Foo( float f )
{
Foo( A< C >( f ) );
}

int main()
{
A< B > ab;
Foo( ab );
float f = 5.0f;
Foo( f ); // ideally implicitly casted to: Foo( A< C >( 5.0f ) );
Foo( int(1) ); // illegal
}
 
B

Brian Byrne

Yes, that works; but...

It's not the genuine implicit coversion I had been hoping for. Rather,
it was the case that I noted as producing duplicate code.

The reason why I want to avoid that method is because I will have
several binary functions (operator+, operator-, etc) in which case I'd
have to write:

// The actual function
template< class T1, class T2 > float operator+( const A< T1 >& lhs,
const A< T2 >& rhs ) { ... }

// Forwarding function
template< class T > float operator+( float lhs, const A< T >& rhs ) {
.... }

// Forwarding function
template< class T > float operator+( const A< T >& lhs, float rhs ) {
.... }

Suppose I wanted type int to be implicitly converted to type A< D >;
I'd be running into 6 forwarding functions, and so on.

As it seems now though, your suggestion is the best choice.

-- Brian Byrne
 
C

Chris Theis

[SNIP]
Suppose I wanted type int to be implicitly converted to type A< D >;
I'd be running into 6 forwarding functions, and so on.

As it seems now though, your suggestion is the best choice.

IMHO Gianni's solution is the best one, but you rather be really careful
with this implicit casting as you might open the door nasty behavior which
is hard to track down. Are you really sure that you need to convert POD to
class objects?

Cheers
Chris
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top