473,414 Members | 1,777 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,414 software developers and data experts.

(Templated) Operator overload on return type.

Hi,

I belive what i am trying to do is not possible, but I hope someone can
change my mind.

Here is some code i'd like to write:

template <class type> class engine1 {};
template <class type> class engine2 {};

template <template <class> class engine, class type>
class optest : public engine<type> {

public:
optest() : data() {}
optest(const optest& copy) : data(copy.data) {}

type data;
};

template <
template <class> class engine, // This isn't legal
template <class> class engine1,
template <class> class engine2,
class type

const optest<engine, type> operator*(
const optest<engine1, type>& op1,
const optest<engine2, type>& op2) {
optest<engine, type> res;
res.data = op1.data * op2.data;
return res;
}

typedef optest<engine1, int> A1;
typedef optest<engine2, int> A2;

int main() {

A1 a1;
A2 a2;

// I'd like all of the operations below to work.

// These are easy ...
a1 = a1 * a1;
a2 = a2 * a2;

a1 = a1 * a2;
a2 = a2 * a1;

// ... but how can I do this
// without getting ambiguity errors, and ..
a1 = a2 * a1;
a2 = a1 * a2;

// ... how can I do this, at all?
a1 = a2 * a2;
a2 = a1 * a1;

return 0;
}

Is there a way, to do this without conversions. (Becuase these would be
expensive, in the real project).

TIA

Fabio


Sep 8 '05 #1
5 2041
"Fabio Fracassi" <f.********@gmx.net> wrote in message
news:df*************@news.t-online.com
Hi,

I belive what i am trying to do is not possible, but I hope someone
can change my mind.
The issue below isn't actually overloading; it is template argument
deduction. But, as with overloading, you can't do it on return type. There
is at least one alternative, however.

Here is some code i'd like to write:

template <class type> class engine1 {};
template <class type> class engine2 {};

template <template <class> class engine, class type>
class optest : public engine<type> {

public:
optest() : data() {}
optest(const optest& copy) : data(copy.data) {}

type data;
};

template <
template <class> class engine, // This isn't legal
It is legal. It is just that the compiler is unable to deduce engine from
the object to which you are assigning the result of the operator. This means
you have to specify it explicitly. See below.
template <class> class engine1,
template <class> class engine2,
class type
>

const optest<engine, type> operator*(
const optest<engine1, type>& op1,
const optest<engine2, type>& op2) {
optest<engine, type> res;
res.data = op1.data * op2.data;
return res;
}

typedef optest<engine1, int> A1;
typedef optest<engine2, int> A2;

int main() {

A1 a1;
A2 a2;

// I'd like all of the operations below to work.

// These are easy ...
a1 = a1 * a1;
a2 = a2 * a2;

a1 = a1 * a2;
a2 = a2 * a1;

// ... but how can I do this
// without getting ambiguity errors, and ..
a1 = a2 * a1;
a2 = a1 * a2;

// ... how can I do this, at all?
a1 = a2 * a2;
a2 = a1 * a1;

return 0;
}

Is there a way, to do this without conversions. (Becuase these would
be expensive, in the real project).


The following compiles (you need the "illegal" line from above). It isn't as
nice to type, but you could use macros/inline functions to make it easier.

int main()
{

A1 a1;
A2 a2;

// I'd like all of the operations below to work.

// These are easy ...
a1 = operator*<engine1>(a1, a1);
a2 = operator*<engine2>(a2, a2);

a1 = operator*<engine1>(a1, a2);
a2 = operator*<engine2>(a2, a1);

// ... but how can I do this
// without getting ambiguity errors, and ..
a1 = operator*<engine1>(a2, a1);
a2 = operator*<engine2>(a1, a2);

// ... how can I do this, at all?
a1 = operator*<engine1>(a2, a2);
a2 = operator*<engine2>(a1, a1);

return 0;
}
--
John Carson

Sep 8 '05 #2
John Carson wrote:
"Fabio Fracassi" <f.********@gmx.net> wrote in message
news:df*************@news.t-online.com
Hi,
The issue below isn't actually overloading; it is template argument
deduction. But, as with overloading, you can't do it on return type.
My mistake sorry.
template <class type> class engine1 {};
template <class type> class engine2 {};

template <template <class> class engine, class type>
class optest : public engine<type> {

public:
optest() : data() {}
optest(const optest& copy) : data(copy.data) {}

type data;
};

template <
template <class> class engine, // This isn't legal


It is legal. It is just that the compiler is unable to deduce engine from
the object to which you are assigning the result of the operator. This
means you have to specify it explicitly. See below.


Yes, of course. Sorry.
The following compiles (you need the "illegal" line from above). It isn't
as nice to type, but you could use macros/inline functions to make it
easier.

a1 = operator*<engine1>(a2, a1);


Yes, but this would somehow defy the purpose of operator overloading,
wouldn't it? I will have to check if expression templates could help here.

Thanks

Fabio




Sep 8 '05 #3
Fabio Fracassi wrote:
Hi,

I belive what i am trying to do is not possible, but I hope someone can
change my mind.

Here is some code i'd like to write:

template <class type> class engine1 {};
template <class type> class engine2 {};

template <template <class> class engine, class type>
class optest : public engine<type> {

public:
optest() : data() {}
optest(const optest& copy) : data(copy.data) {}

type data;
};

template <
template <class> class engine, // This isn't legal
template <class> class engine1,
template <class> class engine2,
class type
> const optest<engine, type> operator*(
const optest<engine1, type>& op1,
const optest<engine2, type>& op2) {
optest<engine, type> res;
res.data = op1.data * op2.data;
return res;
}


These template parameter names used here are confusingly similar to the
class names also in use by the program. It might clarify matters to
declare the operator routine more distinctly:

template <
template <class> class E, // how to determine E?
template <class> class E1,
template <class> class E2,
class T const optest<E, T>
operator*( const optest<E1, T>& op1,
const optest<E2, T>& op2 )
{
optest<E, type> res;

res.data = op1.data * op2.data;
return res;
}
typedef optest<engine1, int> A1;
typedef optest<engine2, int> A2;

int main() {

A1 a1;
A2 a2;

// I'd like all of the operations below to work.

// These are easy ...
a1 = a1 * a1;
a2 = a2 * a2;

a1 = a1 * a2;
a2 = a2 * a1;

// ... but how can I do this
// without getting ambiguity errors, and ..
a1 = a2 * a1;
a2 = a1 * a2;

// ... how can I do this, at all?
a1 = a2 * a2;
a2 = a1 * a1;

return 0;
}

Is there a way, to do this without conversions. (Becuase these would be
expensive, in the real project).


The first task to get this code to compile is to supply the missing
information. Namely, when mutliplying a type A1 object with a type A2
object, what is the type of the resulting product? Will it be of type
A1 or type A2 or some other type completely?

For the sake of discussion let's say the product's type is always the
same type as the lefthand operand:

template <
template <class> class E1,
template <class> class E2,
class T>
const optest<E1, T>
operator*( const optest<E1, T>& op1,
const optest<E2, T>& op2)
{
optest<E1, type> res;

res.data = op1.data * op2.data;
return res;
}

However the program also wants to be able to assign the product to a
variable of the righthand type:

a2 = a1 * a2;

To do so, optest needs to supply a template assignment operator (and
also a converting constructor, but I can't do all the work) in order
for the above statement to compile:

template <
template <class> class engine,
class type>
class optest : public engine<type>
{
public:
optest() : data() {}
optest(const optest& copy) : data(copy.data) {}

template <
template <class> class E, class T >
optest&
operator=( const optest<E, T>& op1 )
{
data = op1.data;
return *this;
}
type data;
};

Now, the sample code provided compiles correctly.

Greg

Sep 9 '05 #4
Greg wrote:
Fabio Fracassi wrote:
Hi, Is there a way, to do this without conversions. (Becuase these would be
expensive, in the real project).

What I wrote above is important! In my real project the class in question
contain (sometimes big, i.e > 1mb) images, so ...
template <
template <class> class E, class T >
optest&
operator=( const optest<E, T>& op1 )
{
data = op1.data;
.... this extra copy of data is a real problem.
return *this;
}
type data;
}; Greg


As I already said in my reply to John, I will probably use some kind of
expression templates, which will also help when using more than one
operator in one expression.

Anyway thanks,

Fabio


Sep 9 '05 #5
Fabio Fracassi wrote:
Greg wrote:
Fabio Fracassi wrote:
Hi, Is there a way, to do this without conversions. (Becuase these would be
expensive, in the real project).


What I wrote above is important! In my real project the class in question
contain (sometimes big, i.e > 1mb) images, so ...
template <
template <class> class E, class T >
optest&
operator=( const optest<E, T>& op1 )
{
data = op1.data;


... this extra copy of data is a real problem.
return *this;
}
type data;
};

Greg


As I already said in my reply to John, I will probably use some kind of
expression templates, which will also help when using more than one
operator in one expression.


You're barking up the wrong tree. Every one of your statements already
creates a copy of the data in a temporary variable and assigns it to
the left hand expression. Copying an A1 object into A2 object with a
programmer-supplied assignment operator is just as efficient (if not
more so) than any of the other copy expressions. The only difference
between:

a1 = a1 * a1;

and

a2 = a1 * a1;

is the that in the first the compiler writes the assignment operator
that copies the right hand expression into a1, while in the second the
programmer has to write the assignment operator to copy the same result
into a2. Otherwise there is no meaningful difference. So if the first
statement is reasonably efficient, then the second one using an
implementation-provided assignment operator, must be as well.

Furthermore if copy operations for these classes are so costly, then
none of the assignment statements in the sample code are reasonable.
But as a practical matter, large data structures should not be held by
value, but should be held indirectly, usually through a shared pointer
as a data member. The class holding the data should have well-thought
out copy semantics. A class whose copy semantics have been thought
through is one that either implements the proper constructor and
assignment operators for copyable types, or declares them private.
After all, data management is often too important to leave up to the
compiler-written routines (which are not even visible in the source
code) to handle.

Greg

Sep 9 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: bsaucer | last post by:
I am creating a class with operator overloads. It makes references to another class I've created, but do not wish to modify. I try to overload an operator having arguments having the other class...
9
by: Jon Wilson | last post by:
I have a class which needs to accumulate data. The way we get this data is by calling a member function which returns float on a number of different objects of different type (they are all the...
4
by: __PPS__ | last post by:
suppose I have class that has templated operator. I want to have a few overloads/template specializations for different types. Basicly, the biggest problem I have is to be able to have this: ...
7
by: Sean | last post by:
Can someone help me see why the following "operator=" overloading doesn't work under g++? and the error message is copied here. I see no reason the compiler complain this. Thanks, $ g++...
17
by: Chris | last post by:
To me, this seems rather redundant. The compiler requires that if you overload the == operator, you must also overload the != operator. All I do for the != operator is something like this: ...
9
by: Tony | last post by:
I have an operator== overload that compares two items and returns a new class as the result of the comparison (instead of the normal bool) I then get an ambiguous operater compile error when I...
3
by: y-man | last post by:
Hi, I am trying to get an overloaded operator to work inside the class it works on. The situation is something like this: main.cc: #include "object.hh" #include "somefile.hh" object obj,...
6
by: alan | last post by:
I'm creating a sort-of "wrapper" class which (partly) acts like a variable. Something like: template<class t> class cell{ t curval; public: /*public for debugging only - will be private in...
1
by: fabian.lim | last post by:
Hi all, Im having a problem with my code. Im programming a vector class, and am trying to overload the () operator in 2 different situations. The first situation is to assign values, e.g. Y =...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
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...
0
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...
0
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...

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.