Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Overloading comma to give a concatenation operator: various problems

Reply
Thread Tools

Overloading comma to give a concatenation operator: various problems

 
 
Paul Davis
Guest
Posts: n/a
 
      07-10-2003
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@/
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      07-10-2003
"Paul Davis" <(E-Mail Removed)> 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


 
Reply With Quote
 
 
 
 
David Cattarin
Guest
Posts: n/a
 
      07-10-2003
Paul Davis <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>. ..
> 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
 
Reply With Quote
 
Erik
Guest
Posts: n/a
 
      07-10-2003

"Victor Bazarov" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "Paul Davis" <(E-Mail Removed)> 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:perator,;
using const_wibble_combiner:perator=;

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:perator,(wibble &w) {
return wibble_combiner(*this, w);
}

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

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

const_wibble_combiner wibble:perator,(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(;
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, w;
cout << hex << l << endl; l = 0;
l = ((w5, w6), w7, w;
cout << hex << l << endl; l = 0;
l = (w5, (w6, w7), w;
cout << hex << l << endl; l = 0;
l = (w5, w6, (w7, w);
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, w;
cout << hex << l;

return 0;
}



 
Reply With Quote
 
Paul Davis
Guest
Posts: n/a
 
      07-15-2003
On Fri, 11 Jul 2003 00:36:21 +0200, "Erik" <(E-Mail Removed)> wrote:

>
>"Victor Bazarov" <(E-Mail Removed)> wrote in message
>news:(E-Mail Removed)...
>> "Paul Davis" <(E-Mail Removed)> wrote...


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

Cheers

Paul
 
Reply With Quote
 
Paul Davis
Guest
Posts: n/a
 
      07-15-2003
On 10 Jul 2003 07:30:36 -0700, http://www.velocityreviews.com/forums/(E-Mail Removed) (David Cattarin)
wrote:

>Paul Davis <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>. ..
>> 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
 
Reply With Quote
 
David Cattarin
Guest
Posts: n/a
 
      07-15-2003
Paul Davis <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>. ..
> On 10 Jul 2003 07:30:36 -0700, (E-Mail Removed) (David Cattarin)
> wrote:
>
> >Paul Davis <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>. ..
> >> 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
 
Reply With Quote
 
Paul Davis
Guest
Posts: n/a
 
      07-17-2003
On 15 Jul 2003 06:49:51 -0700, (E-Mail Removed) (David Cattarin)
wrote:

>Paul Davis <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>. ..
>> On 10 Jul 2003 07:30:36 -0700, (E-Mail Removed) (David Cattarin)
>> wrote:
>>
>> >Paul Davis <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>. ..
>> >> 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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
We dont give only job... We give you the Job Satisfaction....... Anuj Digital Photography 0 01-02-2007 06:35 PM
GIVE ME FILM OR GIVE ME DEATH l#vfgsgEg@AO1.com DVD Video 4 07-14-2005 03:10 PM
Give us 3 minutes; we give you the whole library lib Computer Support 1 02-04-2005 03:16 AM
Give us 3 minutes; we give you the whole library lib Computer Support 0 01-27-2005 07:52 AM
what's the difference between VHDL 93 CONCATENATION and VHDL 87 CONCATENATION? walala VHDL 3 09-18-2003 04:17 AM



Advertisments