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

automatic conversion of template arguments?

P: n/a
Please consider the following scenario below (sketch of).
There are two templates defined: A and B, both with mutual conversion
operators defined.
Also, there's a free function template 'do_something' with the following
signature:

template <class T>
inline void do_something(B<T> const& arg);

Now, given an object of type, say, A<int> passed as a parameter to that
function, the compiler gives up when deducing template arguments. Is it
possible to somehow go around this, without using explicit template
specification? It's a show-stopper for templated operators.

One possible solution I can think of is, of course, to derive both A and
B from some common base class, and use the 'curious base' pattern...
I'd like to keep it simple, though...

See below for the whole picture.

//-------------------------------------------------------------------
// forward declarations
template <class T> class A;
template <class T> class B;

//-------------------------------------------------------------------

template <class T>
class A {
T member;
public:
A(T const& from) : member(from) { }
operator B<T>() const { return member; }
};

//-------------------------------------------------------------------

template <class T>
class B {
T member;
public:
B(T const& from) : member(from) { }
operator A<T>() const { return member; }
};

//-------------------------------------------------------------------

template <class T>
inline void do_something(B<T> const& arg) {
// do something
}

//-------------------------------------------------------------------

int main() {
A<int> a(5);
do_something(a); // ERROR - could not deduce template argument.
do_something<int>(a); // OK
return 0;
}

--
:: bartekd [at] o2 [dot] pl

Jul 22 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
"bartek" <sp******************@o2.pl> wrote in message
template <class T>
class A {
T member;
public:
A(T const& from) : member(from) { }
operator B<T>() const { return member; }
};

//-------------------------------------------------------------------

template <class T>
class B {
T member;
public:
B(T const& from) : member(from) { }
operator A<T>() const { return member; }
};

//-------------------------------------------------------------------

template <class T>
inline void do_something(B<T> const& arg) {
// do something
}

//-------------------------------------------------------------------

int main() {
A<int> a(5);
do_something(a); // ERROR - could not deduce template argument.
do_something<int>(a); // OK
return 0;
}


My compiler Borland C++ Builder 6 gives the error too

[C++ Error] Unit1.cpp(34): E2285 Could not find a match for
'do_something<T>(A<int>)'

The second do_something<int> works.

Don't know the reasons.

See if you really need operator conversions. If it's just nice to have and
leads to a nice syntax, maybe you can do without it. People using operator
conversions say it often results in unwanted conversions, unwanted error
messages, etc, so best bet is to avoid them as much as possible. But use
them as always for proxy objects.
Jul 22 '05 #2

P: n/a
bartek wrote in news:Xn**********************************@153.19.2 51.200 in
comp.lang.c++:
Please consider the following scenario below (sketch of).
There are two templates defined: A and B, both with mutual conversion
operators defined.
Also, there's a free function template 'do_something' with the following
signature:

template <class T>
inline void do_something(B<T> const& arg);

Now, given an object of type, say, A<int> passed as a parameter to that
function, the compiler gives up when deducing template arguments. Is it
possible to somehow go around this, without using explicit template
specification? It's a show-stopper for templated operators.
The compiler can't deduce that a B<T> is called for when given an
A<T> argument, the types are unrelated.

One possible solution I can think of is, of course, to derive both A and
B from some common base class, and use the 'curious base' pattern...
I'd like to keep it simple, though...


There's a whole bunch of tricks you can use, I wouldn't describe
any of them as simple though.

This is about the most straight forward though:

template < typename T >
struct arg_from_template;

template < typename T, template <typename> class C >
struct arg_from_template< C< T > >
{
typedef T type;
};

template < typename T >
void do_something( T const &arg )
{
typedef typename arg_from_template< T >::type real_T;
typedef B< real_T > b_type;

b_type const &real_arg = arg;

// Do whatever with real_arg ...
}

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #3

P: n/a
bartek wrote:

Please consider the following scenario below (sketch of).
There are two templates defined: A and B, both with mutual conversion
operators defined.
Also, there's a free function template 'do_something' with the following
signature:

template <class T>
inline void do_something(B<T> const& arg);

Now, given an object of type, say, A<int> passed as a parameter to that
function, the compiler gives up when deducing template arguments. Is it
possible to somehow go around this, without using explicit template
specification? It's a show-stopper for templated operators.

[snip]

It appears that 14.8.2.4 covers the deduction rules in this case.

I understand you trying to avoid using a template argument list.
Is there any reason you don't want to specify the type conversion
explicitly? I would just do this:

A<int> a(5);
do_something(static_cast<B<int> >(a));

Denis
Jul 22 '05 #4

P: n/a
Denis Remezov <RE*********************@yahoo.removethis.ca> wrote in
news:40***************@yahoo.removethis.ca:
bartek wrote:

Please consider the following scenario below (sketch of).
There are two templates defined: A and B, both with mutual conversion
operators defined.
Also, there's a free function template 'do_something' with the
following signature:

template <class T>
inline void do_something(B<T> const& arg);

Now, given an object of type, say, A<int> passed as a parameter to
that function, the compiler gives up when deducing template
arguments. Is it possible to somehow go around this, without using
explicit template specification? It's a show-stopper for templated
operators.

[snip]

It appears that 14.8.2.4 covers the deduction rules in this case.

I understand you trying to avoid using a template argument list.
Is there any reason you don't want to specify the type conversion
explicitly? I would just do this:

A<int> a(5);
do_something(static_cast<B<int> >(a));


Well, this could be the last resort... I hope it could be done
automatically though.

Say, the class B<T> provides const-reference semantics for A<T>, so both
of them are very closely related, and I'd like it to behave exactly like
the built-in reference in the same context.

--
:: bartekd [at] o2 [dot] pl

Jul 22 '05 #5

P: n/a
Rob Williscroft <rt*@freenet.co.uk> wrote in
news:Xn**********************************@130.133. 1.4:
bartek wrote in
news:Xn**********************************@153.19.2 51.200 in
comp.lang.c++:
Please consider the following scenario below (sketch of).
There are two templates defined: A and B, both with mutual conversion
operators defined.
Also, there's a free function template 'do_something' with the
following signature:

template <class T>
inline void do_something(B<T> const& arg);

Now, given an object of type, say, A<int> passed as a parameter to
that function, the compiler gives up when deducing template
arguments. Is it possible to somehow go around this, without using
explicit template specification? It's a show-stopper for templated
operators.


The compiler can't deduce that a B<T> is called for when given an
A<T> argument, the types are unrelated.

One possible solution I can think of is, of course, to derive both A
and B from some common base class, and use the 'curious base'
pattern... I'd like to keep it simple, though...


There's a whole bunch of tricks you can use, I wouldn't describe
any of them as simple though.

This is about the most straight forward though:

template < typename T >
struct arg_from_template;

template < typename T, template <typename> class C >
struct arg_from_template< C< T > >
{
typedef T type;
};

template < typename T >
void do_something( T const &arg )
{
typedef typename arg_from_template< T >::type real_T;
typedef B< real_T > b_type;

b_type const &real_arg = arg;

// Do whatever with real_arg ...
}


Thanks. That's an option.
However, wouldn't do_something() eat arguments of any type now?
If do_something() was actually, say, templated basic_ostream insert
operator, it wouldn't be OK, would it?

My example code was too vague, I think...
Actually, I'd like class B to implement reference behaviour for class A.

Thanks.
--
:: bartekd [at] o2 [dot] pl

Jul 22 '05 #6

P: n/a
bartek wrote in news:Xn**********************************@153.19.2 51.200
in comp.lang.c++:

Thanks. That's an option.
However, wouldn't do_something() eat arguments of any type now?
If do_something() was actually, say, templated basic_ostream insert
operator, it wouldn't be OK, would it?

Well A simple trick in that case would be to use ADL

namespace stuff
{
// A...
// B...

template < typename Ch, typename Al, typename T >
std::basic_ostream< Ch, Al > &
operator( std::basic_ostream< Ch, Al > &os, T const &arg )
{
}
}

using stuff::A;
using stuff::B;

// *NOT* using namespace stuff;
int main()
{
A< int > ai;

std::cout << ai;
}

My example code was too vague, I think...
Actually, I'd like class B to implement reference behaviour for class
A.


If you only have the two class-templates, A and is "reference" B,
then I'd go with just typing the second overload:

template < typename Ch, typename Al, typename T >
inline std::basic_ostream< Ch, Al > &
operator( std::basic_ostream< Ch, Al > &os, A< T > const &arg )
{
return os << static_cast< B< T > >( arg );
}

It more typing but less fafing about :).

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #7

P: n/a
"bartek" <sp******************@o2.pl> wrote in message
Say, the class B<T> provides const-reference semantics for A<T>, so both
of them are very closely related, and I'd like it to behave exactly like
the built-in reference in the same context.


For this, people often provide a non-explicit constructor B<T>::B(const
A<T>&).

But you say you want a conversion from A<T> to B<T>, and vice versa. What
case is this?
Jul 22 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.