property in C++

T

theambient

hi,

I want make property
(http://en.wikipedia.org/wiki/Property_(programming)) in C++.

In the wiki article explained how to make property in C++ using
template mechanism

this looks like

========================================================================
========================================================================
template <typename T> class property {
T value;
public:
T & operator = (const T &i) {
::std::cout << i << ::std::endl;
return value = i;
}
// This template class member function template serves the
purpose to make
// typing more strict. Assignment to this is only possible with
exact identical
// types.
template <typename T2> T2 & operator = (const T2 &i) {
::std::cout << "T2: " << i << ::std::endl;
T2 &guard = value;
throw guard; // Never reached.
}
operator T const & () const {
return value;
}
};
========================================================================
========================================================================

everything is clear (except never reached throw, aprreciate if anybody
explain it to me)

i wish to extend functionality of this property to get addaptable
setting and getting (mechanism) passed to property as template
arguments.

I see it as pointers to member functions.

so i've implemented something:

========================================================================
========================================================================

#include <iostream>

template <typename T, typename C >
class property {

typedef void(C::*PMANIP)( T & i ) ;

mutable T value;

PMANIP _set;
PMANIP _get;
C & _c;
public:
property( C & c, PMANIP set, PMANIP get ): _set(set), _get(get),
_c(c){}

T & operator = (const T &i) {
value = i;
(_c.*_set)(value);
return value;
}

operator T const & () const {
(_c.*_get)(value);
return value;
}
};


struct Foo {

void set( int &i ){ std::cout << "setting " << i << std::endl; }
void get( int &i ){ std::cout << "getting " << i << std::endl; }



property<int, Foo> val;
Foo():val( *this, &Foo::set, &Foo::get ){}
};

int main(int argc, char** argv )
{
Foo foo;
std::cout << "foo.val = " << foo.val << std::endl;
foo.val = 10;
std::cout << "foo.val = " << foo.val << std::endl;

return 0;
}
========================================================================
========================================================================

really nasty cause we need initialize property in !!!EACH!!!
constructor with class instance reference (*this) and pointers to
setter and getter functions.

As far as i understand pointers to setter and getter can be passed as
template parameters.

How to do it?

I can't make typedef in template parameters list to write something
like
template <typename T, typename C, PMANIP Setter, PMANIP Getter>

and anyway i'll need to initialize property with class instance
reference.
 
J

Jonathan Lee

everything is clear (except never reached throw, aprreciate if anybody
explain it to me)

The throw is never reached because the line above it is invalid
C++ code (in the context of the Wikipedia example). So the
template, when instantiated with T2 == bool, will actually cause
the code to not compile. So... the throw will never be reached.
As far as i understand pointers to setter and getter can be passed as
template parameters.

How to do it?

In the interest of answering your question, like this:

------------------------------------------------------------

#include <iostream>
template <typename T, typename C, void (C::*SETTER)(T&), void
(C::*GETTER)(T&) >
class property {
mutable T value;
C & _c;
public:
property( C & c):value(), _c(c){}
T & operator = (const T &i) {
value = i;
(_c.*SETTER)(value);
return value;
}
operator T const & () const {
(_c.*GETTER)(value);
return value;
}
};

struct Foo {
void set( int &i ){ std::cout << "setting " << i <<
std::endl; }
void get( int &i ){ std::cout << "getting " << i <<
std::endl; }
property<int, Foo, &Foo::set, &Foo::get> val;
Foo():val( *this){}
};

int main(int argc, char** argv )
{
Foo foo;
std::cout << "foo.val = " << foo.val << std::endl;
foo.val = 10;
std::cout << "foo.val = " << foo.val << std::endl;
return 0;
}
 
B

Balog Pal

theambient said:
I want make property
(http://en.wikipedia.org/wiki/Property_(programming)) in C++.

In the wiki article explained how to make property in C++ using
template mechanism

"Property" is one of the most harmful concept, especially counting how
widespread it is. instead of fighting for a hack to infest your C++ code
with it I'd suggest to look for a healthy design... Chances are good it can
be expressed naturally.

Or if you're really into it, pick some environment. I recall Visual C++
handled properties from COM objects so they appeared like simple data
members, arranging all the calls for you in the background. Even back with
version 5.0 15 years ago.
 
M

Maxim Yegorushkin

hi,

I want make property
(http://en.wikipedia.org/wiki/Property_(programming)) in C++.

In the wiki article explained how to make property in C++ using
template mechanism

this looks like

========================================================================
========================================================================
template<typename T> class property {
T value;
public:
T& operator = (const T&i) {
::std::cout<< i<< ::std::endl;
return value = i;
}
// This template class member function template serves the
purpose to make
// typing more strict. Assignment to this is only possible with
exact identical
// types.
template<typename T2> T2& operator = (const T2&i) {
::std::cout<< "T2: "<< i<< ::std::endl;
T2&guard = value;
throw guard; // Never reached.
}
operator T const& () const {
return value;
}
};
========================================================================
========================================================================

everything is clear (except never reached throw, aprreciate if anybody
explain it to me)

i wish to extend functionality of this property to get addaptable
setting and getting (mechanism) passed to property as template
arguments.

I see it as pointers to member functions.

so i've implemented something:

========================================================================
========================================================================

#include<iostream>

template<typename T, typename C>
class property {

typedef void(C::*PMANIP)( T& i ) ;

mutable T value;

PMANIP _set;
PMANIP _get;
C& _c;
public:
property( C& c, PMANIP set, PMANIP get ): _set(set), _get(get),
_c(c){}

T& operator = (const T&i) {
value = i;
(_c.*_set)(value);
return value;
}

operator T const& () const {
(_c.*_get)(value);
return value;
}
};


struct Foo {

void set( int&i ){ std::cout<< "setting "<< i<< std::endl; }
void get( int&i ){ std::cout<< "getting "<< i<< std::endl; }



property<int, Foo> val;
Foo():val( *this,&Foo::set,&Foo::get ){}
};

int main(int argc, char** argv )
{
Foo foo;
std::cout<< "foo.val = "<< foo.val<< std::endl;
foo.val = 10;
std::cout<< "foo.val = "<< foo.val<< std::endl;

return 0;
}
========================================================================
========================================================================

really nasty cause we need initialize property in !!!EACH!!!
constructor with class instance reference (*this) and pointers to
setter and getter functions.

As far as i understand pointers to setter and getter can be passed as
template parameters.

How to do it?

You can do without having to store any extra data in you property
objects. Because object's members are stored at a constant offset from
the beginning of an object you can calculate object's address from the
property address (this) using offsetof() macro from <stddef.h>. (beware,
it does not work with virtual base classes).

Here is how to make a class to support properties:

struct X : with_properties<X>
{
// property tags
struct A {};
struct B {};

// the properties
property<Tag<A>, int> a_;
property<Tag<B>, int> b_;

// helpers, one per property
static size_t getOffset(Tag<A>) { return offsetof(X, a_); }
static size_t getOffset(Tag<B>) { return offsetof(X, b_); }

void set(property<Tag<A>, int>& a, int v)
{
assert(&a == &a_);
a.value = v;
}

void set(property<Tag<B>, int>& b, int v)
{
assert(&b == &b_);
b.value = v;
}

template<class TAG, class T>
T get(property<Tag<TAG>, T> const& p)
{
return p.value;
}
};

In the above, the class needs to do the following to have properties:
1) Derive from with_properties<>.
2) Declare a tag type for every property (A and B here).
3) Declare property members, using property<> template, as above.
4) Implement static helper functions that return the property member
offset. Property tag is passed in that function, so that there can be
one overload of it per property member.
5) Implement get and set functions. These are functions overloaded again
on the tag type, can be templates.

Usage:

int main(int ac, char** av)
{
X x;
x.a_ = 1;
x.b_ = x.a_ + 1;
}

Complete code:

#include <iostream>
#include <cassert>
#include <stdint.h>
#include <stddef.h>

template<class Tag, class T>
struct property
{
T value;

property(T v = T()) : value(v) {}

property& operator=(T v) { set(*this, v); return *this; }
operator T() const { return get(*this); }
};

template<class Derived>
struct with_properties
{
template<class T> struct Tag {};

template<class TAG, class T>
friend void set(property<Tag<TAG>, T>& p, T v)
{

static_cast<Derived&>(*reinterpret_cast<with_properties*>(reinterpret_cast<uintptr_t>(&p)
- Derived::getOffset(Tag<TAG>()))).set(p, v);
}

template<class TAG, class T>
friend T get(property<Tag<TAG>, T> const& p)
{
return
static_cast<Derived&>(*reinterpret_cast<with_properties*>(reinterpret_cast<uintptr_t>(&p)
- Derived::getOffset(Tag<TAG>()))).get(p);
}
};

struct X : with_properties<X>
{
// property tags
struct A {};
struct B {};

// the properties
property<Tag<A>, int> a_;
property<Tag<B>, int> b_;

// helpers, one per property
static size_t getOffset(Tag<A>) { return offsetof(X, a_); }
static size_t getOffset(Tag<B>) { return offsetof(X, b_); }

void set(property<Tag<A>, int>& a, int v)
{
assert(&a == &a_);
a.value = v;
}

void set(property<Tag<B>, int>& b, int v)
{
assert(&b == &b_);
b.value = v;
}

template<class TAG, class T>
T get(property<Tag<TAG>, T> const& p)
{
return p.value;
}
};

int main(int ac, char** av)
{
X x;
x.a_ = 1;
x.b_ = x.a_ + 1;
}
 
T

theambient

Balog said:
"Property" is one of the most harmful concept, especially counting
how widespread it is. instead of fighting for a hack to infest your
C++ code with it I'd suggest to look for a healthy design... Chances
are good it can be expressed naturally.

What's harmful with properties? as far as i understand it makes code
more safe with easy syntax. Do you mean that with property you can't
distinguish at a first glance what you are working with: "plain" member
or property value with some extra logic?
Or if you're really into it, pick some environment. I recall Visual
C++ handled properties from COM objects so they appeared like simple
data members, arranging all the calls for you in the background.
Even back with version 5.0 15 years ago.

No thanks, I'm trying not to use extension especially microsoft ones.
My interest in properties is more academic and just for fun. but anyway
thans. by the way, studio have registered keyword property, at least it
highlight it)))

--
 
T

theambient

Maxim said:
You can do without having to store any extra data in you property
objects. Because object's members are stored at a constant offset
from the beginning of an object you can calculate object's address
from the property address (this) using offsetof() macro from
<stddef.h>. (beware, it does not work with virtual base classes).


thank you for the detailed answer. spent some time understanding it,
but it still have a lot of technical stuff like tags and getOffset.

So there is no much use of such properties...

it's more clear to use direct setter and getters like

class {
T _property;
public:
property( const T & newval ){ _property = newval; }
T &property(){ return _property; }
T const & property() const { return _property; }
};
 
M

Maxim Yegorushkin

thank you for the detailed answer. spent some time understanding it,
but it still have a lot of technical stuff like tags and getOffset.

Tags make property<> a unique type (i.e. property<A, int> and
property<B, int> are distinct unique types) so that function overloading
can be used.

getOffset() gives you the offset of the member from the beginning of the
object, so that you can calculate object's this from member's this.
So there is no much use of such properties...
it's more clear to use direct setter and getters like

Using getter/setter functions gives you no less flexibility with less
unnecessary coding just to make syntax look different.

I just wanted to demonstrate that it is possible to create zero runtime
overhead properties in C++. However, using getter/setter is more
practical in my opinion.
 
A

Alf P. Steinbach /Usenet

* theambient, on 28.07.2010 10:11:
What's harmful with properties? as far as i understand it makes code
more safe with easy syntax. Do you mean that with property you can't
distinguish at a first glance what you are working with: "plain" member
or property value with some extra logic?

Properties are a way to introduce more almost-but-not-quite-identical ways to do
the same thing.

This means extra work to figure out whether to add parenheses or not, more work
to figure out whether something has or can have a side effect or not, and in C++
it additionally means some amount of inefficiency (extra indirection).

Implicit is bad, explicit is good.

No thanks, I'm trying not to use extension especially microsoft ones.
My interest in properties is more academic and just for fun. but anyway
thans. by the way, studio have registered keyword property, at least it
highlight it)))

MSVC has lots of extensions for this and that.

In version 10.0 it can't be relied on to detect all C++ keywords as such.


Cheers,

- Alf
 
R

Ruslan Mullakhmetov

28.07.2010 13:22 said:
* theambient, on 28.07.2010 10:11:

Properties are a way to introduce more almost-but-not-quite-identical
ways to do the same thing.

This means extra work to figure out whether to add parenheses or not,
more work to figure out whether something has or can have a side effect
or not, and in C++ it additionally means some amount of inefficiency
(extra indirection).

Implicit is bad, explicit is good.

Yep, but some syntax sugar would be nice. On the other hand this only
sugar, nothing else...

Once I've been writing tiny app in C#....I was crying how it's glamour,
especially regarding VS intelsence support. Ohhh, just two letters and
it adviced me (correctly) what to write. There is no need to think at
all, VS do all work for you )))

this is was a little digression about sugar )

MSVC has lots of extensions for this and that.

In version 10.0 it can't be relied on to detect all C++ keywords as such.

Never trusted compilers and vendors in this question. Straustrup is only
authoritative source.
 
R

Ruslan Mullakhmetov

I just wanted to demonstrate that it is possible to create zero runtime
overhead properties in C++. However, using getter/setter is more
practical in my opinion.
it was really pleasure to look into this code. I even used something
similar today.

a few more words about setters and getters. Is it normal to use names like
void property( const T & val ); // setter
T const & property(); // getter

or better with prefixes set_ and get_ which is in my opinion a little
bit ugly?
 
R

red floyd

Never trusted compilers and vendors in this question. Straustrup is only
authoritative source.

Actually, ISO 14882:2003 (the C++ Standard) is the only authoritative
source.
 
B

Balog Pal

Ruslan Mullakhmetov said:
a few more words about setters and getters. Is it normal to use names like
void property( const T & val ); // setter
T const & property(); // getter

or better with prefixes set_ and get_ which is in my opinion a little bit
ugly?

Old wisdom states that overloaded functions shall all have the same
semantics. Not quite the case here ;-)

Having the getter without get_ may be okay, but I'd definitely wouldn't like
a setter function not standng out obviously in the code.
 
J

Joshua Maurice

Actually, ISO 14882:2003 (the C++ Standard) is the only authoritative
source.

Actually, a big problem for C++ is there is no useful authoritative
source, partly because the C++ standard is so hard to read, and partly
because implementers are not actually bound to implement the standard
(ex: template export anyone?). Most professionals get along by
reference documents, experience, and Quality of Implementation.
 
R

Ruslan Mullakhmetov

Actually, ISO 14882:2003 (the C++ Standard) is the only authoritative
source.

straustrup's third special edition followed this standard, pardon,
Standard :)
 
J

Jorgen Grahn

straustrup's third special edition followed this standard, pardon,
Standard :)

It's Stroustrup, with an 'o' and a capital 'S'. (I'm not normally that
pedantic, but you misspelled it twice.)

/Jorgen
 
M

Maxim Yegorushkin

it was really pleasure to look into this code. I even used something
similar today.

Thank you.
a few more words about setters and getters. Is it normal to use names like
void property( const T & val ); // setter
T const & property(); // getter

or better with prefixes set_ and get_ which is in my opinion a little
bit ugly?

I prefer being a bit more explicit, so that when you read the code (one
year later) you don't need to guess/lookup what that function call does.
Get/set prefix provides more context to the reader, in my opinion.
 
J

joe

Jorgen said:
It's Stroustrup, with an 'o' and a capital 'S'. (I'm not normally that
pedantic, but you misspelled it twice.)

Give him a break: English does not seem to be his primary language.
 
J

joe

Maxim said:
Thank you.


I prefer being a bit more explicit, so that when you read the code
(one year later) you don't need to guess/lookup what that function
call does. Get/set prefix provides more context to the reader, in my
opinion.

Pick your poison, I guess. Assume methods other than "getters/setters"
begin with an upper-case letter in what follows. (Curb lectures about
leading underscores please).

class Foo
{
int _property;
public:
void property(int prop){ _property = prop; }
int property(){ return _property; }
};

class Foo
{
int _property;
public:
int& property(){ return _property; }
};

struct Foo
{
int _property;
};
 
J

James Kanze

In the wiki article explained how to make property in C++ using
template mechanism

Which is not the normal way of doing it. A "property" in C++ is
no more than a member with a getter and setter having the
externally visible name, e.g.:

class Toto
{
PropertyType myProp;
public:
PropertyType prop() const { return myProp; }
void prop( PropertyType const& newValue )
{ myProp = newValue; }
};

The syntax for accessing a property is different than that for
accessing a member variable, but that's the way C++ works.
 
J

James Kanze

Jorgen Grahn wrote:

[...]
Give him a break: English does not seem to be his primary language.

Spelling a person's name correctly has nothing to do with
whether he's English speaking or not. It's more a question of
politeness.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,076
Latest member
OrderKetoBeez

Latest Threads

Top