|
i am trying to make my own type of string class, but am not being able to overload << for cout and >> for cin. any help?
hari
|
|
|
|
|
#include <tchar.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<typename t,="" char="" propertytype=""> class Property {
private:
T myVar;
public:
Property() {
if ( PropertyType != 'r' && PropertyType != 'w' && PropertyType != 'b' ) {
throw "Invalid PropertyType. PropertyTypes allowed are :: \n\tr ->Read , w -> Write , b -> Both Read and Write.";
}
}
operator T() {
return GetValue();
}
void operator = ( T theVar ) {
SetValue(theVar);
}
virtual T GetValue() {
if ( PropertyType == 'w' ) {
throw "Cannot read from a write-only property";
}
return myVar;
}
virtual void SetValue(T theVar) {
if ( PropertyType == 'r' ) {
throw "Cannot write to a read-only property";
}
myVar = theVar;
}
};
int _tmain(int argc, _TCHAR* argv[]) {
try
{
Property<string ,'e'=""> aStringProperty;
aStringProperty = "Anand";
string aStrProp = aStringProperty;
cout << "Previosly assigned :: " << "Anand " << "Retrived from property :: " << aStrProp;
Property<vector<int> , 'b'> aVectorProperty;
vector<int> aVector;
aVector.push_back(1);aVector.push_back(2);aVector.push_back(3);aVector.push_back(4);aVector.push_back(5);
aVectorProperty = aVector;
vector<int> aNewVector = aVectorProperty;
cout << "\n\nInitialised vector with values 1,2,3,4,5. Retrieving from vector property ::\n";
for ( int i = 0 ; i < 5 ; i++ ) {
cout << aNewVector [ i ] << endl;
}
} catch( char* theException ) {
cout << "\n\nException Occured : \n--------------------\n Message : " << theException ;
}
_getch();
return 0;
}
Thanks and Regards,
Anand.
|
|
|
|
|
Actual class definition is like template(typename T, char PropertyType) class Property
Also the read the include section as
#include (tchar.h)
#include (conio.h)
#include (iostream)
#include (string)
#include (vector)
I dont know why the "less than symbol and greator than symbol" are dissappearing here ...so i used "(" for them....
Thanks and Regards,
Anand.
|
|
|
|
|
Why so complicated?
Simpler is this:
//Visual C++ 7
class PropTest
{
public:
PropTest(){};
int getCount() const {return m_nCount;}
void setCount(int nCount){ m_nCount = nCount;}
__declspec(property(get=getCount, put=setCount)) int Count;
private:
int m_nCount;
};
---
Mit freundlichen Grüßen
-- Siegfried Bauer --
|
|
|
|
|
Hi,
Did you read the first part of the article, I want to implement a portable property across compiler using standard C++ without any extension, __declspec is a MS VC extension, likewise there is C++Builder extension and manages C++ extension, but all these extension will work only on one compiler.
Regards,
Emad
|
|
|
|
|
i think your property implementation can be improved in the following way so that your compiler helps you detect access errors to read_only or write_only properties:
enum EPropProperty
{
READ_ONLY = 0,
WRITE_ONLY = 1,
READ_WRITE = 2
};
template< unsigned int i >
struct IntToType
{
enum { ret = i };
};
template< typename ValType, class Owner, EPropProperty Prop >
class PropertyImpl;
template< typename ValType, class Owner >
class PropertyImpl< ValType, Owner, READ_ONLY >
{
public:
typedef ValType (Owner::*GetMethod)() const;
protected:
void PutGetter( GetMethod pFnGet )
{ m_pFnGet = pFnGet; }
GetMethod m_pFnGet;
};
template< typename ValType, class Owner >
class PropertyImpl< ValType, Owner, WRITE_ONLY >
{
public:
typedef void (Owner::*SetMethod)( const ValType &rhs );
protected:
void PutSetter( SetMethod pFnSet )
{ m_pFnSet = pFnSet; }
SetMethod m_pFnSet;
};
template< typename ValType, class Owner >
class PropertyImpl< ValType, Owner, READ_WRITE >
: public PropertyImpl< ValType, Owner, READ_ONLY >
, public PropertyImpl< ValType, Owner, WRITE_ONLY >
{
};
template< typename ValType, class Owner, EPropProperty Prop >
class Property
: public PropertyImpl< ValType, Owner, Prop >
{
friend class Owner;
public:
typedef typename PropertyImpl< ValType, Owner, READ_ONLY >::GetMethod GetMethod;
typedef typename PropertyImpl< ValType, Owner, WRITE_ONLY >::SetMethod SetMethod;
Property( Owner *const pThis )
: m_pThis( pThis ) {}
Property( Owner *const pThis, GetMethod pFnGet )
: m_pThis( pThis )
{
PropertyImpl< ValType, Owner, Prop >::PutGetter( pFnGet );
}
Property( Owner *const pThis, SetMethod pFnSet )
: m_pThis( pThis )
{
PropertyImpl< ValType, Owner, Prop >::PutSetter( pFnSet );
}
Property( Owner *const pThis, GetMethod pFnGet, SetMethod pFnSet )
: m_pThis( pThis )
{
PropertyImpl< ValType, Owner, Prop >::PutGetter( pFnGet );
PropertyImpl< ValType, Owner, Prop >::PutSetter( pFnSet );
}
~Property() {}
operator ValType()
{
return( GetValue( IntToType< Prop >() ) );
}
void operator =( const ValType &rhs )
{
SetValue( rhs, IntToType< Prop >() );
}
private:
template< EPropProperty Prop >
ValType GetValue( IntToType< Prop > );
template<>
ValType GetValue( IntToType< READ_ONLY > )
{ return( (m_pThis->*m_pFnGet)() ); }
template<>
ValType GetValue( IntToType< WRITE_ONLY > )
{
class {} property_is_write_only[ 0 ];
}
template<>
ValType GetValue( IntToType< READ_WRITE > )
{ return( (m_pThis->*m_pFnGet)() ); }
template< EPropProperty Prop >
void SetValue( const ValType &rhs, IntToType< Prop > );
template<>
void SetValue( const ValType &rhs, IntToType< READ_ONLY > )
{
class {} property_is_read_only[ 0 ];
}
template<>
void SetValue( const ValType &rhs, IntToType< WRITE_ONLY > )
{ (m_pThis->*m_pFnSet)( rhs ); }
template<>
void SetValue( const ValType &rhs, IntToType< READ_WRITE > )
{ (m_pThis->*m_pFnSet)( rhs ); }
private:
Owner* m_pThis;
};
You can use it in the following way:
class A
{
public:
A()
: ReadOnlyProperty( this, A::GetReadOnlyProperty )
, WriteOnlyProperty( this, A::SetWriteOnlyProperty )
, AllAccessProperty( this, A::GetAllAccessProperty, A::SetAllAccessProperty )
, m_iReadOnlyProperty( 10 )
, m_dWriteOnlyProperty( 5.5 )
, m_cAllAccessProperty( 'A' )
{
}
void AlternativeSetter( const char &c )
{}
Property< int, A, READ_ONLY > ReadOnlyProperty;
Property< double, A, WRITE_ONLY > WriteOnlyProperty;
Property< char, A, READ_WRITE > AllAccessProperty;
private:
void
SetWriteOnlyProperty( const double &val )
{ m_dWriteOnlyProperty = val; }
int
GetReadOnlyProperty() const
{ return( m_iReadOnlyProperty ); }
char
GetAllAccessProperty() const
{ return( m_cAllAccessProperty ); }
void
SetAllAccessProperty( const char &val )
{ m_cAllAccessProperty = val; }
private:
int m_iReadOnlyProperty;
double m_dWriteOnlyProperty;
char m_cAllAccessProperty;
};
A a;
cout << a.ReadOnlyProperty << endl; // OK
a.ReadOnlyProperty = 5; // results in a compiler error
cout << a.WriteOnlyProperty << endl; // results in a compiler error
a.WriteOnlyProperty = 6.8; // OK
cout << a.AllAccessProperty << endl; // OK
a.AllAccessProperty = 'B'; // OK
// a client cannot do something like this
a.AllAccessProperty.PutSetter( A::AlternativeSetter );
|
|
|
|
|
Hi
I was trying to implement your version and i ran into tons of compiler problems. After i did some modifications, some of them went away but i can get past the following problem :
when it compiles the following :
A()
: ReadOnlyProperty( this, A::GetReadOnlyProperty )
, WriteOnlyProperty( this, A::SetWriteOnlyProperty )
, AllAccessProperty( this, A::GetAllAccessProperty, A::SetAllAccessProperty )
, m_iReadOnlyProperty( 10 )
, m_dWriteOnlyProperty( 5.5 )
, m_cAllAccessProperty( 'A' )
{
}
__thiscall CProperty<int,class a,0="">::CProperty<int,class a,0="">(class A *const ,int (__thiscall Owner::*)(void) const)' : cannot convert parameter 2 from 'int (void) const' to 'int (__th
iscall Owner::*)(void) const'
I wondered if you could give some advise on this ?
Thanks
MASUD
Masud
masud_masud@hotmail.com
|
|
|
|
|
In my project I need to clone classes. In that case it is easy if I can assign corresponding properties to one another. To do that, add the following code to the property class in the public section:
property operator =(const property& value)<br />
{<br />
assert(m_Container != NULL);<br />
assert(Set != NULL);<br />
(m_Container->*Set)((value.m_Container->*value.Get)()); <br />
return *this;<br />
}<br />
friend property;
Good stuff, the property class. I like simple, effective things that use standard C++ and/or stl.
|
|
|
|
|
sorry about the length, buth all the operators are here. Note that there is no Postincrement or decrement operators included as they generated errors when used with classes such as strings
const unsigned READ_ONLY = 0x01;
const unsigned WRITE_ONLY = 0x02;
const unsigned READ_WRITE = 0x03;
template <typename container, typename T, unsigned type>
class property
{
public:
property(container* o = NULL): object(o), setter(NULL), getter(NULL) {}
void SetContainer(container* o) { object = o; }
void Setter(void (container::*set)(T v))
{
assert(type & WRITE_ONLY);
setter = set;
}
void Getter(T (container::*get)())
{
assert(type & READ_ONLY);
getter = get;
}
T operator =(const T& value)
{
assert((object != NULL) && (setter != NULL));
(object->*setter)(value);
return value;
}
operator T()
{
assert((object != NULL) && (getter != NULL));
return (object->*getter)();
}
template <typename Type>
T operator+(Type v2) { return (object->*getter)() + (T)v2; }
template <typename Type>
T operator-(Type v2) { return (object->*getter)() - (T)v2; }
template <typename Type>
T operator*(Type v2) { return (object->*getter)() * (T)v2; }
template <typename Type>
T operator/(Type v2) { return (object->*getter)() / (T)v2; }
template <typename Type>
T operator%(Type v2) { return (object->*getter)() % (T)v2; }
template <typename Type>
T operator^(Type v2) { return (object->*getter)() ^ (T)v2; }
template <typename Type>
T operator|(Type v2) { return (object->*getter)() | (T)v2; }
template <typename Type>
T operator&(Type v2) { return (object->*getter)() & (T)v2; }
template <typename Type>
T operator<<(Type v2) { return (object->*getter)() << (T)v2; }
template <typename Type>
T operator>>(Type v2) { return (object->*getter)() >> (T)v2; }
template <typename Type>
property operator+=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() + (T)v);
return *this;
}
template <typename Type>
property operator-=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() - (T)v);
return *this;
}
template <typename Type>
property operator*=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() * (T)v);
return *this;
}
template <typename Type>
property operator/=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() / (T)v);
return *this;
}
template <typename Type>
property operator%=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() % (T)v);
return *this;
}
template <typename Type>
property operator^=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() ^ (T)v);
return *this;
}
template <typename Type>
property operator|=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() | (T)v);
return *this;
}
template <typename Type>
property operator&=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() & (T)v);
return *this;
}
template <typename Type>
property operator<<=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() << (T)v);
return *this;
}
template <typename Type>
property operator>>=(Type v)
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() >> (T)v);
return *this;
}
const property &operator++()
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() + 1);
return *this;
}
const property &operator--()
{
assert((object != NULL) && (setter != NULL) && (getter != NULL));
(object->*setter)((object->*getter)() - 1);
return *this;
}
private:
container* object;
void (container::*setter)(T v);
T (container::*getter)();
};
|
|
|
|
|
Hello sir
gcc / mingw does not seem to compiel it, it reports at
'friend property;'
you may try it using devc++ which comes with mingw compiler.
Waiting for kind reply.
regards
easy GUI building www.radcpp.com
|
|
|
|
|
That is because using either
friend property; or
friend class property; attempts to redefine the class template for property.
It is fixed with the following anywhere inside the class utilizing the property library:
template <typename Container, typename ValueType, int nPropType>
friend class property;
|
|
|
|
|
How about next MSVC attribute?
<br />
__declspec( property( get=get_func_name, put=put_func_name ) )<br />
(seach a topic in MSDN by word 'property')
May be it's an easy way, than using templates?
Ken Keray
|
|
|
|
|
Hi,
I know about the property of Visual C++, but the problem that Visual C++ property or Boland C++Builder property are extension to the C++ language, I want in this article to show how to implement a portable standard c++ property that can be compiled by any C++ compiler.
Regards,
Emad
|
|
|
|
|
maybe you can tweak your code so it takes advantage of the __declspec(property) when _MSC_VER is defined?
I like the idea of properties - but the overhead of the container reference has always kept me away from it.
Just an idea
"Der Geist des Kriegers ist erwacht / Ich hab die Macht" StS
sighist | Agile Programming | doxygen
|
|
|
|
|
a better solution is to keep the size of the container
4byte(sizeof(void*)),
getter,and setter should be written specifically to achieve
automation, that is, not only to perform a simple get and set,
but also to change some other things, a single pointer to the
actual data will saffice, getter and setter are implemented
as member functions of that property.
those with read-only attribute set, can be regarded as they
have only
operator ValType () const;
method.
and so on.
|
|
|
|
|
My own implementation (a bit of template madness) that I wrote this evening, takes care of operators, and you'll get compile time errors if you are trying to write to a read-only property. Compiles with VC.NET 2002. Example code at bottom, well commented as always.
class property_void {};
template <typename owner_type_, typename value_type_>
class getter;
template <typename owner_type_, typename value_type_>
class setter;
template <typename owner_type_, typename value_type_, typename property1_type_, typename property2_type_ = property_void>
class property;
template <typename owner_type_, typename value_type_>
class property_base
{
public:
typedef owner_type_ owner_type;
typedef value_type_ value_type;
typedef getter<owner_type, value_type> getter_type;
typedef setter<owner_type, value_type> setter_type;
typedef property<owner_type, value_type, getter_type, setter_type> readwrite_property_type;
typedef property<owner_type, value_type, getter_type> readonly_property_type;
typedef property<owner_type, value_type, setter_type> writeonly_property_type;
friend getter_type;
friend setter_type;
property_base(owner_type* owner_)
: owner(owner_)
{
}
private:
owner_type* owner;
};
template <typename owner_type_, typename value_type_>
class getter
{
public:
typedef owner_type_ owner_type;
typedef value_type_ value_type;
typedef value_type (owner_type_::*getter_func_type)() const;
typedef property_base<owner_type, value_type> property_base_type;
getter(property_base_type* property_base_, getter_func_type getter_func_)
: property_base(property_base_),
getter_func(getter_func_)
{
}
value_type get_value() const
{
return (*property_base->owner.*getter_func)();
}
private:
property_base_type* property_base;
getter_func_type getter_func;
};
template <typename owner_type_, typename value_type_>
class setter
{
public:
typedef owner_type_ owner_type;
typedef value_type_ value_type;
typedef void (owner_type_::*setter_func_type)(value_type);
typedef property_base<owner_type, value_type> property_base_type;
setter(property_base_type* property_base_, setter_func_type setter_func_)
: property_base(property_base_),
setter_func(setter_func_)
{
}
void set_value(const value_type& rhs)
{
(*property_base->owner.*setter_func)(rhs);
}
private:
property_base_type* property_base;
setter_func_type setter_func;
};
template <typename owner_type_, typename value_type_, typename property1_type_, typename property2_type_ = property_void>
class property : public property_base<owner_type_, value_type_>, private property1_type_, private property2_type_
{
public:
typedef owner_type_ owner_type;
typedef value_type_ value_type;
typedef property1_type_ property1_type;
typedef property2_type_ property2_type;
typedef property_base<owner_type, value_type> property_base_type;
typedef property<owner_type, value_type, property1_type, property2_type> this_type;
property(owner_type* owner_, property1_type property1_)
: property_base_type(owner_),
property1_type(property1_)
{
}
property(owner_type* owner_, property1_type property1_, property2_type property2_)
: property_base_type(owner_),
property1_type(property1_),
property2_type(property2_)
{
}
const value_type& operator=(const value_type& rhs)
{
set_value(rhs);
return rhs;
}
operator value_type()
{
return get_value();
}
value_type operator++()
{
set_value(get_value() + 1);
return get_value();
}
value_type operator++(int)
{
const value_type value = get_value();
set_value(value + 1);
return value;
}
value_type operator--()
{
set_value(get_value() - 1);
return get_value();
}
value_type operator--(int)
{
const value_type value = get_value();
set_value(value + 1);
return value;
}
template <typename rhs_type>
value_type operator+=(const rhs_type& rhs)
{
set_value(get_value() + rhs);
return get_value();
}
template <typename rhs_type>
value_type operator-=(const rhs_type& rhs)
{
set_value(get_value() - rhs);
return get_value();
}
template <typename rhs_type>
value_type operator*=(const rhs_type& rhs)
{
set_value(get_value() * rhs);
return get_value();
}
template <typename rhs_type>
value_type operator/=(const rhs_type& rhs)
{
set_value(get_value() / rhs);
return get_value();
}
template <typename rhs_type>
value_type operator%=(const rhs_type& rhs)
{
set_value(get_value() % rhs);
return get_value();
}
template <typename rhs_type>
value_type operator<<=(const rhs_type& rhs)
{
set_value(get_value() << rhs);
return get_value();
}
template <typename rhs_type>
value_type operator>>=(const rhs_type& rhs)
{
set_value(get_value() >> rhs);
return get_value();
}
template <typename rhs_type>
value_type operator^=(const rhs_type& rhs)
{
set_value(get_value() ^ rhs);
return get_value();
}
template <typename rhs_type>
value_type operator&=(const rhs_type& rhs)
{
set_value(get_value() & rhs);
return get_value();
}
template <typename rhs_type>
value_type operator|=(const rhs_type& rhs)
{
set_value(get_value() | rhs);
return get_value();
}
private:
property(const this_type& rhs);
const this_type& operator=(const this_type& rhs);
};
#include <iostream>
class foo
{
typedef property_base<foo, int> count_property_base_type;
typedef count_property_base_type::readwrite_property_type count_property_type;
typedef count_property_type::getter_type count_getter_type;
typedef count_property_type::setter_type count_setter_type;
typedef property_base<foo, int> bar_property_base_type;
typedef bar_property_base_type::readonly_property_type bar_property_type;
typedef bar_property_type::getter_type bar_getter_type;
public:
foo()
: Count(this, count_getter_type(&Count, &foo::get_count), count_setter_type(&Count, &foo::set_count)),
Bar(this, bar_getter_type(&Bar, &foo::get_bar)),
count(0),
bar(47)
{
}
int get_count() const { return count; }
void set_count(int count_) { count = count_; }
int get_bar() const { return bar; }
count_property_type Count;
bar_property_type Bar;
private:
int count;
int bar;
};
int main()
{
foo foo;
foo.Count = 13;
std::cout << "(foo.Count) = " << (foo.Count) << std::endl;
std::cout << "(foo.Count++) = " << (foo.Count++) << std::endl;
std::cout << "(++foo.Count) = " << (++foo.Count) << std::endl;
std::cout << "(foo.Count %= 10) = " << (foo.Count %= 10) << std::endl;
std::cout << "(foo.Bar) = " << foo.Bar << std::endl;
} Output:
(foo.Count) = 13
(foo.Count++) = 13
(++foo.Count) = 15
(foo.Count %= 10) = 5
(foo.Bar) = 47
|
|
|
|
|
|
|
You mean a property for an array of values? That's a bit different and the code will need some changing. One way of doing it would be to create a new property_array class that holds and array of properties to values, but that solution could be a bit bloaty if done incorrectly.
// Dalle
|
|
|
|
|
I was thinking that the template would be simpler if it just owned
the value. Also, the container class would not need to have a
getter and setter. What do you think of an approach like this:
const unsigned property_readOnly = 0x01;
const unsigned property_writeOnly = 0x02;
const unsigned property_readWrite = 0x03;
template <typename ValueType, unsigned permissions>
class property
{
public:
property( ValueType initialValue ) : m_value(initialValue), m_permissions(permissions)
{
}
ValueType operator =(const ValueType& value)
{
assert( permissions & property_writeOnly );
m_value = value;
return value;
}
operator ValueType()
{
assert( permissions & property_readOnly );
return m_value;
}
private:
const unsigned m_permissions;
ValueType m_value;
};
class PropTest
{
public:
PropTest() : Count(0) {}
property<int,property_readWrite> Count;
}
(I apologize if the code doesn't compile -- I don't have a compiler
handy and I am not experience with templates.)
(As in the article, I've just asserted for permission violations.
In real code I would prefer using mechanisms so that permission
violations would not compile.)
|
|
|
|
|
Using this template property of yours is as good as making the variable public as everyone will have the same access to it. The getter and setter are the whole point, ok not the whole point but much of it.
|
|
|
|
|
Well, I thought that the point of a property was that you *don't*
have getters and setters, from the point of view of client code.
Anyway, I'm not seeing what you are seeing. The data is hidden
inside the property. Consider the alternatives for an int:
class PropTestA
{
public:
property<PropTest,int,READ_WRITE> Count;
private:
int GetCount() { return m_nCount; }
void SetCount( int nCount ) { m_nCount = nCount; }
int m_nCount;
};
class PropTestB
{
public:
PropTest() : Count(0) {}
property<int,property_readWrite> Count;
}
class PropTestC
{
public:
int Count;
}
Client usage and semantics for routine use are the same
for all three cases:
PropTestX p;
p.Count = 7;
int i = p.Count;
However, with both templates you cannot
int *pi = &p.Count;
++p.Count;
because Count is not an int, it's a property!
The same distinction applies if our property
value is a class instead of an int. With
public data clients would have access to every
operation on the class. With either template
solution, all they can do is read and write
the property value.
Could you tell me how the approach I've described
is more like public data than the article's template?
----
As long as the property value is something that the
property owner owns wholely/directly, I don't see
how the approach I've described is worse. With a
class, ValueType::operator=() does the same thing
as Container::Set(), and ValueType's copy constructor
does the same thing as Container::Get().
If the property value were something owned indirectly
by Container, like this
class PropTestA2
{
public:
property<PropTest,int,READ_WRITE> Count;
private:
int GetCount() { return m_someClass.GetCount(); }
void SetCount( int nCount ) { m_someClass.SetCount(nCount); }
CounterClass m_someClass;
};
then the approach I've described doesn't work.
Against this disadvantage, you avoid having to
write the getter and setter, and avoid the function
pointer indirection.
Are there other disadvantages you see?
|
|
|
|
|
davidmontgomery wrote:
Well, I thought that the point of a property was that you *don't* have getters and setters, from the point of view of client code.
That is true, from the client's view you don't want getters and setters. But you'll still want to be able to define them to validate/update the data from within the class.
davidmontgomery wrote:
Could you tell me how the approach I've described is more like public data than the article's template?
As I said:
Dalle wrote:
Using this template property of yours is as good as making the variable public as everyone will have the same access to it.
If the property itself owns the data the owner of the property will not have 'better' access to the data than any other class, and thus cannot manipulate/validate the data without going through the property. If the property only have simple passthrough member functions, as in your example, the property will not have any purpose, it has the same effect as a const or non-const member variable for read-only and read-write access respectively. The only thing it accomplishes it to make code like ++p.Count to not work.
|
|
|
|
|
I like this implementaion for a property. I took the liberty of adding operators and adding a set function to allow the iniliation of a READ_ONLY value if its not set by the constructor. It only allows one write though, so its secure if used properly (ie. a flag to show if something has been created or not, read-only, but cant be inialized to a specific value.
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
const unsigned READ_ONLY = 0x01;
const unsigned WRITE_ONLY = 0x02;
const unsigned READ_WRITE = 0x03;
template <typename T, unsigned permissions>
class property
{
public:
property(T v): value(v), type(permissions), lock(true) {}
property(): type(permissions), lock(false) {}
void Set(T v)
{
if(lock != true) lock = true;
else assert(type & WRITE_ONLY);
value = v;
}
T operator =(const T& v)
{
assert(type & WRITE_ONLY);
value = v;
return value;
}
operator T()
{
assert(type & READ_ONLY);
return value;
}
template <typename Type>
T operator+(Type v2) { return value + (T)v2; }
template <typename Type>
T operator-(Type v2) { return value - (T)v2; }
template <typename Type>
T operator*(Type v2) { return value * (T)v2; }
template <typename Type>
T operator/(Type v2) { return value / (T)v2; }
template <typename Type>
T operator%(Type v2) { return value % (T)v2; }
template <typename Type>
T operator^(Type v2) { return value ^ (T)v2; }
template <typename Type>
T operator&(Type v2) { return value & (T)v2; }
template <typename Type>
T operator|(Type v2) { return value | (T)v2; }
template <typename Type>
T operator<<(Type v2) { return value << (T)v2; }
template <typename Type>
T operator>>(Type v2) { return value >> (T)v2; }
template <typename Type>
property operator+=(Type v2) { return value += (T)v2; return *this; }
template <typename Type>
property operator-=(Type v2) { return value -= (T)v2; return *this; }
template <typename Type>
property operator*=(Type v2) { return value *= (T)v2; return *this; }
template <typename Type>
property operator/=(Type v2) { return value /= (T)v2; return *this; }
template <typename Type>
property operator%=(Type v2) { return value %= (T)v2; return *this; }
template <typename Type>
property operator^=(Type v2) { return value ^= (T)v2; return *this; }
template <typename Type>
property operator&=(Type v2) { return value &= (T)v2; return *this; }
template <typename Type>
property operator|=(Type v2) { return value |= (T)v2; return *this; }
template <typename Type>
property operator<<=(Type v2) { return value <<= (T)v2; return *this; }
template <typename Type>
property operator>>=(Type v2) { return value >>= (T)v2; return *this; }
const property &operator++() { ++value; return *this; }
property operator++(int) { value++; return *this; }
const property &operator--() { --value; return *this; }
property operator--(int) { value--; return *this; }
private:
const unsigned type;
bool lock;
T value;
};
class PropTest
{
public:
PropTest(): Count(0) {}
property<int, READ_WRITE> Count;
property<string, READ_WRITE> Text;
};
int main()
{
PropTest test; test.Count = 5;
int cool = test.Count * 100;
test.Count = test.Count + 1;
cout << cool << " " << test.Count << endl;
test.Text.Set("HI"); string out = test.Text + string("hello");
cout << "Text flag: " << out << endl;
test.Count.Set(5);
++test.Count;
cout << test.Count << endl;
test.Count--;
if(test.Count == 5)
cout << test.Count << endl;
test.Count *= (-2) + 6;
cout << test.Count << endl;
system("pause");
return 0;
}
|
|
|
|
|
What about other operator support, like operator+=(cref) , operator-=(cref) , operator++() , operator--() , operator++(int) , operator--(int) and any other assigning operator out there?
|
|
|
|
|