473,612 Members | 2,115 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

automatic conversion of template arguments?

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<in t>(a); // OK
return 0;
}

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

Jul 22 '05 #1
7 1823
"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<in t>(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<in t> 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
bartek wrote in news:Xn******** *************** ***********@153 .19.251.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_templa te;

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

template < typename T >
void do_something( T const &arg )
{
typedef typename arg_from_templa te< 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
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(st atic_cast<B<int > >(a));

Denis
Jul 22 '05 #4
Denis Remezov <RE************ *********@yahoo .removethis.ca> wrote in
news:40******** *******@yahoo.r emovethis.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(st atic_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
Rob Williscroft <rt*@freenet.co .uk> wrote in
news:Xn******** *************** ***********@130 .133.1.4:
bartek wrote in
news:Xn******** *************** ***********@153 .19.251.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_templa te;

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

template < typename T >
void do_something( T const &arg )
{
typedef typename arg_from_templa te< 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
bartek wrote in news:Xn******** *************** ***********@153 .19.251.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_ostr eam< Ch, Al > &
operator( std::basic_ostr eam< 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_ostr eam< Ch, Al > &
operator( std::basic_ostr eam< 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
"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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
1707
by: ES Kim | last post by:
Consider: #include <string> #include <iostream> using namespace std; struct S { const char* ps_; operator string();
3
1922
by: BigMan | last post by:
Here is a piece of code: #include <memory> using namespace std; template< typename SomeType > void f(auto_ptr_ref< SomeType >) { }
3
1382
by: Kevin Ruland | last post by:
Hi all. I have a template class with conversion operator: template< typename T > class FooWrapper { public: FooWrapper( const T& rhs ); }
5
3026
by: Vijai Kalyan | last post by:
Hello, I have come back to C++ after a couple of years with Java so I am quite rusty and this question may seem poor: My platform is Windows XP with MSVC 7.1. I have a class with a templatized conversion operator defined as follows:
16
2980
by: frs | last post by:
See example below: Why does the output of 'a' work and the output of 'b' fails to compile? Is there a way to write class 'something' so that 'b' converts correctly by default? (include iostream, string, use namespace std) template <typename T> struct something { T x; operator T();
15
2572
by: Alexander Stippler | last post by:
hi, the following does not work. I do not understand why, since it works if I replace line marked by (1) with the line below ((2)). Compiling with gcc4.0 results in "error: conversion from 'Two<int>' to non-scalar type 'One<int>' requested". Has somebody an explanation for me? template <typename T> struct Convert
2
9781
by: Arvid Requate | last post by:
Hello, I'd like to understand why the following code does not compile. It looks like a strangeness in connection with overload resolution for the <complex> header: The conversion operator double() of class B is called for the member complex::operator*=(double) as expected, but not for operator*(complex, double). The effect is, that the template matching (or overload resolution)
3
1824
by: Szabolcs | last post by:
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---------------
9
2886
by: puzzlecracker | last post by:
From my understanding, if you declare any sort of constructors, (excluding copy ctor), the default will not be included by default. Is this correct? class Foo{ public: Foo(int); // no Foo() is included, i believe. };
0
8105
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8605
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8246
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7039
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6076
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5532
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4045
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4109
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1695
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.