Page 1 of 1

C# Properties in C++

Posted: Wed Jul 25, 2007 6:49 am
by os64dev
Hi all,

I have been busy with C# programming at work and found out that i sort of like Properties but standard C++ is lacking this feature. So i set out to do some coding and achieved the following scalar property template don't complain about formatting because that easy to change :wink:

Code: Select all

template <typename T>
class               Property {
  public:
    explicit Property<T>() : _value() {}

    explicit Property<T>(const T & data) : _value(data) {set(data);}

    Property<T>(const Property<T> & rhs) {set(rhs._value);}

    const T &       operator = (const T & data) {set(data);}

    const Property<T> &       operator = (const Property<T> & rhs) { set(rhs._value); return(*this); }

    operator T () { return(get()); }

    template <typename X>
    void       operator = (const X & rhs) {
        _value = rhs;
    }
    template <typename X>
    operator X () {
        return((X)_value);
    }

  protected:
    virtual const T &   get(void){return(_value);}
    virtual void        set(const T & data){_value = data;}
  private:
    T                   _value;
};
how is this helpfull one might wonder, but think about queues and such. Lets use a fixed size fifo. albeit a very simple one :D.

Code: Select all

template <typename T, int N>
class FIFO {
    T       _buffer[N];
    int     _indexSet, _indexGet;
  public:
  FIFO() : _indexGet(0), _indexSet(0){}
    void       operator = (const T & data) {
        _buffer[_indexSet++] = data;
    }
    operator T () {
        return(_buffer[_indexGet++]);
    }
};
now we can use the fifo as a property, so lets consider the following program:

Code: Select all

    Property<FIFO<int, 10> >      fifo;

    for(int i =0; i < 10; i++) fifo = i;
    for(int i =0; i < 10; i++) printf("%d ", (int)fifo);
it stores the values 0 - 9 in the queue and gets them from the queue again. so the outcome of this program is: 0 1 2 3 4 5 6 7 8 9. nice huh no more adding and removing functions just using the elements of queue.

creating a LIFO like :

Code: Select all

template <typename T, int N>
class LIFO {
    T       _buffer[N];
    int     _index;
  public:
  LIFO() : _index(0) {}
    void       operator = (const T & data) {
        _buffer[_index++] = data;
    }
    operator T () {
        return(_buffer[_index--]);
    }
};
and using the same code snippet except with using the LIFO instead of the FIFO;

Code: Select all

    Property<LIFO<int, 10> >      lifo;

    for(int i =0; i < 10; i++) lifo = i;
    for(int i =0; i < 10; i++) printf("%d ", (int)lifo);
yields the result: 9 8 7 6 5 4 3 2 1 0. the metod of using the LIFO or FIFO is quite the same. You might wonder how efficient the code might be so here is the object dump of the FIFO example and it shows that is very ptiomised:

Code: Select all

   Property<FIFO<int, 10> >      fifo;

    for(int i =0; i < 10; i++) fifo = i;
  401264:	31 d2                	xor    %edx,%edx
  401266:	89 8d 58 ff ff ff    	mov    %ecx,0xffffff58(%ebp)
  40126c:	c7 45 88 00 00 00 00 	movl   $0x0,0xffffff88(%ebp)
  401273:	8d b6 00 00 00 00    	lea    0x0(%esi),%esi
  401279:	8d bc 27 00 00 00 00 	lea    0x0(%edi),%edi
  401280:	8b 5d 84             	mov    0xffffff84(%ebp),%ebx
  401283:	8d 4a 01             	lea    0x1(%edx),%ecx
  401286:	89 14 9e             	mov    %edx,(%esi,%ebx,4)
  401289:	43                   	inc    %ebx
  40128a:	83 f9 09             	cmp    $0x9,%ecx
  40128d:	89 5d 84             	mov    %ebx,0xffffff84(%ebp)
  401290:	89 ca                	mov    %ecx,%edx
  401292:	7e ec                	jle    401280 <_main+0x230>
  401294:	bb 09 00 00 00       	mov    $0x9,%ebx
  401299:	8d b4 26 00 00 00 00 	lea    0x0(%esi),%esi
  4012a0:	8b 45 88             	mov    0xffffff88(%ebp),%eax
  4012a3:	8b 14 86             	mov    (%esi,%eax,4),%edx
  4012a6:	8d 48 01             	lea    0x1(%eax),%ecx
  4012a9:	89 4d 88             	mov    %ecx,0xffffff88(%ebp)
  4012ac:	c7 04 24 31 30 40 00 	movl   $0x403031,(%esp)
  4012b3:	89 54 24 04          	mov    %edx,0x4(%esp)
  4012b7:	e8 94 13 00 00       	call   402650 <_printf>
  4012bc:	4b                   	dec    %ebx
  4012bd:	79 e1                	jns    4012a0 <_main+0x250>
    for(int i =0; i < 10; i++) printf("%d ", (int)fifo);
hope you find this usefull and am looking forward to your remark etc.

Posted: Wed Jul 25, 2007 7:34 am
by AJ
A yes here!

I also come from a C# ([cough]and vb.net[cough]) background. When I went from C to C++ I was quite disappointed as I had expected to find properties among the features. I never thought of your template method, damnit :P

Posted: Wed Jul 25, 2007 8:06 am
by AndrewAPrice
By properties, do you mean like

Code: Select all

int myvariable
{
    get
    {
        return m_myvariable;
    }
    set
    {
        m_myvariable = value
    }
}
in C#? Maybe we should ask ANSI if they'd include it in their C standard :D.

Posted: Wed Jul 25, 2007 2:13 pm
by os64dev
indeed those properties :wink: even with support beyond the basic value types or primitive types as they are called in c++, hence the FIFO/LIFO example. but even message passing, IPC, mailboxes, pipes can be build this way, tough you can argue if you should the << and >> operators for that like is done with streams.

Very even distributed poll at this point 2/2/2. I see that there are 2 garbage votes but now explanations why, a shame i would have liked to know why.

Posted: Wed Jul 25, 2007 11:35 pm
by Colonel Kernel
os64dev wrote:I see that there are 2 garbage votes but now explanations why, a shame i would have liked to know why.
I wouldn't use this technique in production code because it adds too much complexity for too little gain. It's hard enough to find qualified C++ programmers these days (they don't seem to teach C++ at universities anymore) -- I wouldn't set junior developers loose on code like that unless there were a very clear benefit to doing so.

Posted: Thu Jul 26, 2007 12:08 am
by pcmattman
I'd use it.

Posted: Thu Jul 26, 2007 12:20 am
by os64dev
Colonel Kernel wrote: I wouldn't use this technique in production code because it adds too much complexity for too little gain. It's hard enough to find qualified C++ programmers these days (they don't seem to teach C++ at universities anymore) -- I wouldn't set junior developers loose on code like that unless there were a very clear benefit to doing so.
Properties were originally designed for GUI applications and RAD tools with VB as the main example i guess. That is also were they are the most used and suited for. For a experienced C++ programmer it indeed means more complexity and little gain as he/she knows other techniques, however as you said C/C++ is hardly tought on schools anymore but C# is. This template helps in bringing that C# behaviour to C++, though it might be in vain due to an artikel i read about properties being added to future version of C++.

Posted: Thu Jul 26, 2007 4:05 pm
by Candy
Same here about a year ago, but whilst making the properties I figured that I wanted to be able to assign a properties value plus something, times something else to another property. Something Windows pretends to do with docking and adding offsets but doesn't quite accomplish.

I then set out to make that and have succeeded. I posted it here and nobody picked up on its application as properties. The most important part of it I found was that you could give it a function to call when it changed; you would be informed of a change.



Now, not to be mean but I did vote "garbage" - I was vote #3 on that.

Your template explicitly implements a policy it could and should have delegated to a template inner class:

Code: Select all

template <typename A, template <typename> class StorePolicy>
class property {
...

protected:
   StorePolicy<A> store;
   set(const A &val) { store.set(val); }
   A get() { return store.get(); }
};
You abuse operators for a very unclear purpose - don't use operator= for inserting. If I see you make a loop over 10 values of i assigning each in sequence to anything I'm going to generalise that the last value will be the current value and that the rest can be taken away trivially.

Not to mention that I fail to see how a FIFO or LIFO queue would be related to a property.

I also miss the point of having these wrappers. I can't add code to use the values set, I can't add code to mask values being returned. I can't even be informed of changing values as they change, which is what I would consider the most important part of a property object.

Posted: Fri Jul 27, 2007 3:38 am
by os64dev
Candy wrote:Same here about a year ago, but whilst making the properties I figured that I wanted to be able to assign a properties value plus something, times something else to another property. Something Windows pretends to do with docking and adding offsets but doesn't quite accomplish.

I then set out to make that and have succeeded. I posted it here and nobody picked up on its application as properties. The most important part of it I found was that you could give it a function to call when it changed; you would be informed of a change.
I just wanted to assing data to a property and have a basic setter and getter. No additional notify functions as that would increase the memory usage of the property by two pointers. one for the containing objects and one for the function pointer. Though i can see the advantages of your solution. I will search the forum for it.
Candy wrote:Now, not to be mean but I did vote "garbage" - I was vote #3 on that.
That's not mean, that you given right in a poll. :wink:
Candy wrote:Your template explicitly implements a policy it could and should have delegated to a template inner class:

Code: Select all

template <typename A, template <typename> class StorePolicy>
class property {
...

protected:
   StorePolicy<A> store;
   set(const A &val) { store.set(val); }
   A get() { return store.get(); }
};
Well honestly i don't know templates that good or C++ for that matter as i used C most of my professional life. Embedded software and C++ don't mix they say. Indeed your solution described above is better but i implemented the above in less then an hour to see if i could get scalar properties in C++.
Candy wrote: You abuse operators for a very unclear purpose - don't use operator= for inserting. If I see you make a loop over 10 values of i assigning each in sequence to anything I'm going to generalise that the last value will be the current value and that the rest can be taken away trivially.

Not to mention that I fail to see how a FIFO or LIFO queue would be related to a property.
Yes it was not designed properly i agree and the abuse was needed to get the LIFO and FIFO working, ahem. These i used however to show that the property was not only usable for value/primitive types but also reference types, but indeed other examples might have been better.

EDIT:
I tried to find you post/code but could not find it. any help?

Posted: Fri Jul 27, 2007 6:29 am
by Candy
os64dev wrote:I tried to find you post/code but could not find it. any help?
http://www.osdev.org/phpBB2/viewtopic.p ... ht=dynamic

Not much time to explain, will probably react next time in the weekend

Posted: Fri Jul 27, 2007 8:01 am
by os64dev
very fun stuff those dynamics. very useable in spread sheets i guess. It seem very different from my conceptual view to properties. It feels more that your dynamics are... how to put it .. Properties++ or Properties on a next plane of existence. Well hope to hear your explanations in the weekend ;-)

Posted: Sun Jul 29, 2007 1:53 pm
by Candy
os64dev wrote:very fun stuff those dynamics. very useable in spread sheets i guess. It seem very different from my conceptual view to properties. It feels more that your dynamics are... how to put it .. Properties++ or Properties on a next plane of existence. Well hope to hear your explanations in the weekend ;-)
Took until sunday evening to get to a laptop with internet, but anyway :)

The idea came from the Windows hack of "docking" or tying a given property to a given source, with a given human calculation in between. I figured that (in combination with streams) the concept of a variable that would change autonomically and tell you about what it did, plus combining logic for tying those objects together, would form a powerful mechanism. It's a bit like a cell from a spreadsheet, but without the sheet behind it. You use it in much the same way too - you take a cell, put a value in it, assign a result of a calculation with that value to another cell. People have created huge programs in spreadsheets - you can make the same programs in a nonprocedural way with this too.

For the UI, you would assign a value to Width based on parent.width and to Left based on something (probably nothing). When parent.width changed, this.width also changes and informs you that it did so. You need only redraw. If you use more complex methods of tying objects together, this is a boon. Try to make a UI package in which you have a window with a split screen in vertical - the left half is 40%, the right is 60%. Now make it keep those properties when dragged. Resorting to

onResize() {
child1.width = width * 0.4;
child2.width = width * 0.6;
}

doesn't fix the problem, as you're likely to forget these fixes once in a while.

There's still a bit more behind these variables - I'm analysing them at the moment since there are a few corner cases that aren't handled properly. I would like to be able to indicate ranges for target values, so the source knows within which bounds it can properly regulate a given output, and there's a subtle difference between "local" and "remote" values, where local values are actual containers that store the value for future use (possibly in solid state memory or EEPROMs, or interactively from hardware inputs) and remote values are that value only because some components informs you about it.

Properties per se are very useful imo - as public child objects, even when your teachers object - but the given implementation isn't good.

Posted: Sun Jul 29, 2007 7:19 pm
by AndrewAPrice
Candy wrote:Took until sunday evening to get to a laptop with internet, but anyway :)
How many people here are interested in OS devving and don't have their own computer?

Posted: Tue Jul 31, 2007 2:59 pm
by Candy
MessiahAndrw wrote:
Candy wrote:Took until sunday evening to get to a laptop with internet, but anyway :)
How many people here are interested in OS devving and don't have their own computer?
That would be my holiday. I have three laptops and 8 other computers, but that doesn't help when none are near a wifi point, another internet connection or at home.

Hi OS64DEV

Posted: Thu Aug 23, 2007 10:36 pm
by DeletedAccount
Hi .. OS64DEV ..,
That's quite an orginal idea .... I did like it very much....