473,392 Members | 1,319 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,392 software developers and data experts.

Overloading comma to give a concatenation operator: various problems

I'd like to overload 'comma' to define a concatenation operator for
integer-like classes. I've got some first ideas, but I'd appreciate a
sanity check. The concatenation operator needs to so something like
this:

1) e = (a, b, c, d); // concatenate a,b,c,d into e
2) (a, b, c, d) = e; // get the bits of e into a,b,c, and d

For example, in the second case, assume that a,b,c,d represent 2-bit
integers, and e represents an 8-bit integer. If e contains 0b10110100,
then after the assignment, a contains 0b10, b contains 0b11, and so
on.

My current thinking, for the second case, is:

1) Overload comma for the new integer class. This needs several (3?)
prototypes, because the operands may be const temporaries.

2) In the second example, 'a,b' is evaluated first. This results in a
temporary, so I return a const reference to the temporary. This
requires this operator:

const wibble& operator , (wibble&, wibble&) // proto 1

3) '(temporary , c)' is then evaluated. This requires this operator:

const wibble& operator , (const wibble&, wibble&) // proto 2

4) Eventually, we end up with a temporary which has 'e' assigned to
it, which needs this operator:

const wibble& operator= (wibble&) // proto 3
(or just void operator= (wibble&)?)

If this makes sense, my first problem is how to get the value of 'e',
which is only seen by operator=, into the the a, b, c, and d objects.
Any ideas? Currently, my only idea is that the comma operator should
store a reference to its operands in a global list somewhere, and
operator= then runs through the list assigning to all the wibbles in
it. This doesn't feel good, and there's also the question of when to
initialise the list. However, I guess I could do this with the comma
operators which have a non-const left operand, since they should
always be used for the first comma evaluation.

Next question: what if the user wants to do

(a, (b, c), d) = e;

Is this possible? Does the temporary result of (b,c) go out of scope
before it can be used to evaluate (a, (b,c))? If this is Ok,
presumably it would require a third comma operator:

const wibble& operator , (wibble&, const wibble&)

Does any of this make sense?

Many thanks

Paul
______________________________________
To get a valid mail address: s/m@/m1@/
Jul 19 '05 #1
7 8008
"Paul Davis" <no*****@no.spam.com> wrote...
I'd like to overload 'comma' to define a concatenation operator for
integer-like classes. I've got some first ideas, but I'd appreciate a
sanity check. The concatenation operator needs to so something like
this:

1) e = (a, b, c, d); // concatenate a,b,c,d into e
2) (a, b, c, d) = e; // get the bits of e into a,b,c, and d

For example, in the second case, assume that a,b,c,d represent 2-bit
integers, and e represents an 8-bit integer. If e contains 0b10110100,
then after the assignment, a contains 0b10, b contains 0b11, and so
on.

My current thinking, for the second case, is:

1) Overload comma for the new integer class. This needs several (3?)
prototypes, because the operands may be const temporaries.

2) In the second example, 'a,b' is evaluated first. This results in a
temporary, so I return a const reference to the temporary.
I'd return a value.
This
requires this operator:

const wibble& operator , (wibble&, wibble&) // proto 1
I'd do it

wibble operator ,(wibble&, wibble&);

3) '(temporary , c)' is then evaluated. This requires this operator:

const wibble& operator , (const wibble&, wibble&) // proto 2
Again, return a value instead

wibble operator ,(const wibble&, wibble&)

4) Eventually, we end up with a temporary which has 'e' assigned to
it, which needs this operator:

const wibble& operator= (wibble&) // proto 3
(or just void operator= (wibble&)?)
The default signature of the assignment operator would be

wibble& operator =(const wibble&)

or

wibble& operator =(wibble&)

depending on whether you want to be able to assign from
a temporary or not.
If this makes sense, my first problem is how to get the value of 'e',
which is only seen by operator=, into the the a, b, c, and d objects.
Any ideas? Currently, my only idea is that the comma operator should
store a reference to its operands in a global list somewhere, and
operator= then runs through the list assigning to all the wibbles in
it. This doesn't feel good, and there's also the question of when to
initialise the list. However, I guess I could do this with the comma
operators which have a non-const left operand, since they should
always be used for the first comma evaluation.

Next question: what if the user wants to do

(a, (b, c), d) = e;

Is this possible? Does the temporary result of (b,c) go out of scope
before it can be used to evaluate (a, (b,c))? If this is Ok,
presumably it would require a third comma operator:

const wibble& operator , (wibble&, const wibble&)

Does any of this make sense?


I think what you need is some kind of 'lazy evaluator' class that
would store the values of all those wibbles and then when assigned
to something would evaluate the wibbles and combine them or spread
them around.

class wibble_combiner
{
list<wibble*> candidates;
bool spreading; // should be 'true' by default
list<wibble> values;

public:

wibble_combiner(wibble&); // starts by putting
// this wibble in 'candidates'
// switches 'spreading' on

wibble_combiner(const wibble&); // starts by putting
// this wibble in 'values'
// switches 'spreading' off

wibble_combiner& operator ,(wibble&); // if spreading,
// adds to 'candidates'
// otherwise - to 'values'

wibble_combiner& operator ,(const wibble&); // turns spreading off
// forms 'values' if not formed
// adds the wibble to 'values'

wibble_combiner& operator ,(const wibble_combiner&);

wibble_combiner& operator =(const wibble&); // to spread
// will do nothing or throw
// if 'spreading' is 'false'

operator wibble() const; // conversion -- to combine,
// regardless of 'spreading'
};
How's that? Well, try it, see if you can get anywhere. Post
your results or, if you have any, your questions.

Victor
Jul 19 '05 #2
Paul Davis <no*****@no.spam.com> wrote in message news:<b3********************************@4ax.com>. ..
I'd like to overload 'comma' to define a concatenation operator for
integer-like classes. I've got some first ideas, but I'd appreciate a
sanity check.


Well let's see:
1. Don't do it.
2. Read More Effective C++.
3. Don't do it.

Aside from the fact that it will be more confusing to people that
don't realize that you've changed the semantics of the comma operator,
I think you'll also find that it will cause you problems.

Look at it this way, what do you think myFn( a, b, c ) should do?

I'll suggest that you either define a good method name (like concat)
or use the "standard" operator for concatenation: +=.

With a method name like concat you could do:
x = a.concat( b ).concat( c ).concat( d ).concat( e );
IMO, this is clearer in intent than:
x = a, b, c, d, e;

Dave
Jul 19 '05 #3

"Victor Bazarov" <v.********@attAbi.com> wrote in message
news:vg************@corp.supernews.com...
"Paul Davis" <no*****@no.spam.com> wrote...
I'd like to overload 'comma' to define a concatenation operator for
integer-like classes. I've got some first ideas, but I'd appreciate a
sanity check. The concatenation operator needs to so something like
this:

1) e = (a, b, c, d); // concatenate a,b,c,d into e
2) (a, b, c, d) = e; // get the bits of e into a,b,c, and d

For example, in the second case, assume that a,b,c,d represent 2-bit
integers, and e represents an 8-bit integer. If e contains 0b10110100,
then after the assignment, a contains 0b10, b contains 0b11, and so
on.

My current thinking, for the second case, is:

1) Overload comma for the new integer class. This needs several (3?)
prototypes, because the operands may be const temporaries.

2) In the second example, 'a,b' is evaluated first. This results in a
temporary, so I return a const reference to the temporary.
I'd return a value.
This
requires this operator:

const wibble& operator , (wibble&, wibble&) // proto 1


I'd do it

wibble operator ,(wibble&, wibble&);

3) '(temporary , c)' is then evaluated. This requires this operator:

const wibble& operator , (const wibble&, wibble&) // proto 2


Again, return a value instead

wibble operator ,(const wibble&, wibble&)

4) Eventually, we end up with a temporary which has 'e' assigned to
it, which needs this operator:

const wibble& operator= (wibble&) // proto 3
(or just void operator= (wibble&)?)


The default signature of the assignment operator would be

wibble& operator =(const wibble&)

or

wibble& operator =(wibble&)

depending on whether you want to be able to assign from
a temporary or not.
If this makes sense, my first problem is how to get the value of 'e',
which is only seen by operator=, into the the a, b, c, and d objects.
Any ideas? Currently, my only idea is that the comma operator should
store a reference to its operands in a global list somewhere, and
operator= then runs through the list assigning to all the wibbles in
it. This doesn't feel good, and there's also the question of when to
initialise the list. However, I guess I could do this with the comma
operators which have a non-const left operand, since they should
always be used for the first comma evaluation.

Next question: what if the user wants to do

(a, (b, c), d) = e;

Is this possible? Does the temporary result of (b,c) go out of scope
before it can be used to evaluate (a, (b,c))? If this is Ok,
presumably it would require a third comma operator:

const wibble& operator , (wibble&, const wibble&)

Does any of this make sense?


I think what you need is some kind of 'lazy evaluator' class that
would store the values of all those wibbles and then when assigned
to something would evaluate the wibbles and combine them or spread
them around.

class wibble_combiner
{
list<wibble*> candidates;
bool spreading; // should be 'true' by default
list<wibble> values;

public:

wibble_combiner(wibble&); // starts by putting
// this wibble in 'candidates'
// switches 'spreading' on

wibble_combiner(const wibble&); // starts by putting
// this wibble in 'values'
// switches 'spreading' off

wibble_combiner& operator ,(wibble&); // if spreading,
// adds to 'candidates'
// otherwise - to 'values'

wibble_combiner& operator ,(const wibble&); // turns spreading off
// forms 'values' if not

formed // adds the wibble to 'values'

wibble_combiner& operator ,(const wibble_combiner&);

wibble_combiner& operator =(const wibble&); // to spread
// will do nothing or throw
// if 'spreading' is 'false'

operator wibble() const; // conversion -- to combine,
// regardless of 'spreading'
};


Here's my try. Compiles and produces expected results with VC++ 7.0.
Try adding (w1, w2, w5, w4) = l to main and it won't compile (because w5 is
const).
If anyone has a better suggestion, please correct me.

#include <list>
#include <iostream>
#include <climits>

class wibble_combiner;
class const_wibble_combiner;

class wibble {
public:
wibble(unsigned char v) : value(v) {}
const wibble &operator=(unsigned char v) { value = v; return *this; }
operator unsigned char() const { return value; }

wibble_combiner operator,(wibble &);
const_wibble_combiner operator,(const wibble &) const;
wibble_combiner operator,(const wibble_combiner &);
const_wibble_combiner operator,(const const_wibble_combiner &) const;

private:
unsigned char value;
friend class wibble_combiner;
friend class const_wibble_combiner;
};

class const_wibble_combiner {
public:
operator unsigned long() const {
unsigned long l = 0;
for (std::list<const wibble *>::const_iterator I = lst.begin(); I !=
lst.end(); I++)
l = l << CHAR_BIT | (*I)->value;
return l;
}

const_wibble_combiner operator,(const const_wibble_combiner &c) const {
const_wibble_combiner rslt(*this);
rslt.lst.insert(rslt.lst.end(), c.lst.begin(), c.lst.end());
return rslt;
}

const_wibble_combiner operator,(const wibble &w) const {
const_wibble_combiner rslt(*this);
rslt.lst.push_back(&w);
return rslt;
}

private:
explicit const_wibble_combiner(const wibble &w1, const wibble &w2) {
lst.push_back(&w1);
lst.push_back(&w2);
}

const_wibble_combiner(const const_wibble_combiner &c) : lst(c.lst) {}
const_wibble_combiner &operator=(const const_wibble_combiner &c) { lst =
c.lst; }

std::list<const wibble *> lst;

friend class wibble;
friend class wibble_combiner;
};

class wibble_combiner : public const_wibble_combiner {
public:
using const_wibble_combiner::operator,;
using const_wibble_combiner::operator=;

unsigned long operator=(unsigned long l) {
long result = l;
for (std::list<const wibble *>::reverse_iterator I = lst.rbegin(); I !=
lst.rend(); I++) {
(const_cast<wibble *>(*I))->value = (unsigned char)l;
l >>= CHAR_BIT;
}
return result;
}

const wibble_combiner &operator=(const const_wibble_combiner &c) {
std::list<const wibble *>::reverse_iterator I1 = lst.rbegin();
std::list<const wibble *>::const_reverse_iterator I2 = c.lst.rbegin();
for (; I1 != lst.rend() && I2 != c.lst.rend(); I1++, I2++) {
(const_cast<wibble *>(*I1))->value = (*I2)->value;
}
while (I1 != lst.rend())
(const_cast<wibble *>(*I1))->value = 0;

return *this;
}

wibble_combiner operator,(const wibble_combiner &c) const {
wibble_combiner rslt(*this);
rslt.lst.insert(rslt.lst.end(), c.lst.begin(), c.lst.end());
return rslt;
}

wibble_combiner operator,(wibble &w) const {
wibble_combiner rslt(*this);
rslt.lst.push_back(&w);
return rslt;
}

private:
explicit wibble_combiner(wibble &w1, wibble &w2) :
const_wibble_combiner(w1, w2) {}

wibble_combiner(const wibble_combiner &c) : const_wibble_combiner(c) {}

friend class wibble;
};
wibble_combiner wibble::operator,(wibble &w) {
return wibble_combiner(*this, w);
}

const_wibble_combiner wibble::operator,(const wibble &w) const {
return const_wibble_combiner(*this, w);
}

wibble_combiner wibble::operator,(const wibble_combiner &c) {
wibble_combiner rslt(c);
rslt.lst.push_front(this);
return rslt;
}

const_wibble_combiner wibble::operator,(const const_wibble_combiner &c)
const {
const_wibble_combiner rslt(c);
rslt.lst.push_front(this);
return rslt;
}

int main() {
using std::cout;
using std::hex;
using std::endl;

wibble w1(1), w2(2), w3(3), w4(4);
const wibble w5(5), w6(6), w7(7), w8(8);
long l = 0;

l = (w1, w2, w3, w4);
cout << hex << l << endl; l = 0;
l = ((w1, w2), w3, w4);
cout << hex << l << endl; l = 0;
l = (w1, (w2, w3), w4);
cout << hex << l << endl; l = 0;
l = (w1, w2, (w3, w4));
cout << hex << l << endl; l = 0;

l = (w5, w6, w7, w8);
cout << hex << l << endl; l = 0;
l = ((w5, w6), w7, w8);
cout << hex << l << endl; l = 0;
l = (w5, (w6, w7), w8);
cout << hex << l << endl; l = 0;
l = (w5, w6, (w7, w8));
cout << hex << l << endl; l = 0;

l = 0x0a0b0c0d;
(w1, w2, w3, w4) = l;
cout << (int)w1 << " " << (int)w2 << " " << (int)w3 << " " << (int)w4 <<
endl; w1 = 1; w2 = 2; w3 = 3; w4 = 4;
((w1, w2), w3, w4) = l;
cout << (int)w1 << " " << (int)w2 << " " << (int)w3 << " " << (int)w4 <<
endl; w1 = 1; w2 = 2; w3 = 3; w4 = 4;
(w1, (w2, w3), w4) = l;
cout << (int)w1 << " " << (int)w2 << " " << (int)w3 << " " << (int)w4 <<
endl; w1 = 1; w2 = 2; w3 = 3; w4 = 4;
(w1, w2, (w3, w4)) = l;
cout << (int)w1 << " " << (int)w2 << " " << (int)w3 << " " << (int)w4 <<
endl; w1 = 1; w2 = 2; w3 = 3; w4 = 4;

l = (w1, w2, w3, w4) = (w5, w6, w7, w8);
cout << hex << l;

return 0;
}

Jul 19 '05 #4
On Fri, 11 Jul 2003 00:36:21 +0200, "Erik" <no@spam.com> wrote:

"Victor Bazarov" <v.********@attAbi.com> wrote in message
news:vg************@corp.supernews.com...
"Paul Davis" <no*****@no.spam.com> wrote...


Thanks Victor/Erik - this has been very useful; I've got some working
code now.

Cheers

Paul
Jul 19 '05 #5
On 10 Jul 2003 07:30:36 -0700, di****@ix.netcom.com (David Cattarin)
wrote:
Paul Davis <no*****@no.spam.com> wrote in message news:<b3********************************@4ax.com>. ..
I'd like to overload 'comma' to define a concatenation operator for
integer-like classes. I've got some first ideas, but I'd appreciate a
sanity check.


There's a hidden agenda - the users of this code will be more used to
hardware description languages, where what I described is the standard
'bit concatenation' mechanism.
Well let's see:
1. Don't do it.
2. Read More Effective C++.


Ah, if only. However, I've still got another 2,000 pages to get
through in the 4 books I've already got. I'm not expecting to finish
this side of the grave.

Thanks

Paul
Jul 19 '05 #6
Paul Davis <no*****@no.spam.com> wrote in message news:<qf********************************@4ax.com>. ..
On 10 Jul 2003 07:30:36 -0700, di****@ix.netcom.com (David Cattarin)
wrote:
Paul Davis <no*****@no.spam.com> wrote in message news:<b3********************************@4ax.com>. ..
I'd like to overload 'comma' to define a concatenation operator for
integer-like classes. I've got some first ideas, but I'd appreciate a
sanity check.


There's a hidden agenda - the users of this code will be more used to
hardware description languages, where what I described is the standard
'bit concatenation' mechanism.


Ah... In that case, these people are familiar with this convention.
Out of curiosity, which HDL are you referring to?

One of the strong-points of C++ is that it does allow you to do such
things. This can also backfire if the "new" features cause curious
interactions. In any case, I thought it fair to warn you.
Well let's see:
1. Don't do it.
2. Read More Effective C++.


Ah, if only. However, I've still got another 2,000 pages to get
through in the 4 books I've already got. I'm not expecting to finish
this side of the grave.


LOL. I understand that feeling.
Good luck,
Dave
Jul 19 '05 #7
On 15 Jul 2003 06:49:51 -0700, di****@ix.netcom.com (David Cattarin)
wrote:
Paul Davis <no*****@no.spam.com> wrote in message news:<qf********************************@4ax.com>. ..
On 10 Jul 2003 07:30:36 -0700, di****@ix.netcom.com (David Cattarin)
wrote:
>Paul Davis <no*****@no.spam.com> wrote in message news:<b3********************************@4ax.com>. ..
>> I'd like to overload 'comma' to define a concatenation operator for
>> integer-like classes. I've got some first ideas, but I'd appreciate a
>> sanity check.
>


There's a hidden agenda - the users of this code will be more used to
hardware description languages, where what I described is the standard
'bit concatenation' mechanism.


Ah... In that case, these people are familiar with this convention.
Out of curiosity, which HDL are you referring to?


The only commercially significant HDLs are Verilog and VHDL. Verilog
concatenation is much the same as I described above:

// X=1'b1, Y=2'b01
Z = {X, Y, 3'b001}; // Z = 6'b101001

The concatention can also appear as an lvalue. VHDL was derived from
Ada, and uses the '&' operator for concatenating any 1D arrays; ie.
"abc" & 'd' = "abcd", b"0001" & b"0101" = b"00010101", etc.

SystemC is a relatively new HDL, and is actually a C++ class library;
it does concatenation exactly as I described above.

Cheers

Paul
Jul 19 '05 #8

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

Similar topics

4
by: Dave Theese | last post by:
Hello all, I'm trying to get a grasp of the difference between specializing a function template and overloading it. The example below has a primary template, a specialization and an overload. ...
6
by: Zenon | last post by:
Folks, I am having a terrible time overloading operators. I have tried what I thought was the correct way, I tried the cheating (friend declarations), all to no avail. Sorry for posting tons of...
9
by: Silver | last post by:
Hi everyone, I want to overload the ! operator, so that when I write this in main x! I can get the factorial of x. The problem is, that the operator I want to overload takes no parameter. Most...
11
by: Shawn Odekirk | last post by:
Some code I have inherited contains a macro like the following: #define setState(state, newstate) \ (state >= newstate) ? \ (fprintf(stderr, "Illegal...
6
by: TuxC0d3 | last post by:
Hi! I'm diving into the some more ++ specific aspects of c++ (and finally accepting that c++ is more than "a plus added to c" :), so that means using namespaces, templates, std::strings, lists,...
35
by: josh | last post by:
Hi, I coded the following but It does not return what I expect, why? #include <iostream> using namespace std; class Other { public: int i;
5
by: ashu | last post by:
i have studied this example of overloading operator, but i don`t know exactly what happened in code .kindly explain me: #include <iostream> using namespace std; const int SIZE = 3; class...
8
by: Wayne Shu | last post by:
Hi everyone, I am reading B.S. 's TC++PL (special edition). When I read chapter 11 Operator Overloading, I have two questions. 1. In subsection 11.2.2 paragraph 1, B.S. wrote "In particular,...
4
by: =?ISO-8859-1?Q?Tom=E1s_=D3_h=C9ilidhe?= | last post by:
Operator overloads are just like any other member function, you can make them do whatever you want. However, of course, we might expect them to behave in a certain way. The ++ operator should...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
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
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...
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...

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.