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 5 1908
"Fabio Fracassi" <f.********@gmx.net> wrote in message
news:df*************@news.tonline.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
John Carson wrote: "Fabio Fracassi" <f.********@gmx.net> wrote in message news:df*************@news.tonline.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
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
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
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
programmersupplied 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
implementationprovided 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 wellthought
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
compilerwritten routines (which are not even visible in the source
code) to handle.
Greg This discussion thread is closed Replies have been disabled for this discussion. Similar topics
5 posts
views
Thread by bsaucer 
last post: by

9 posts
views
Thread by Jon Wilson 
last post: by

4 posts
views
Thread by __PPS__ 
last post: by

7 posts
views
Thread by Sean 
last post: by

17 posts
views
Thread by Chris 
last post: by

9 posts
views
Thread by Tony 
last post: by

3 posts
views
Thread by yman 
last post: by

6 posts
views
Thread by alan 
last post: by

1 post
views
Thread by fabian.lim 
last post: by
          