473,408 Members | 2,734 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,408 software developers and data experts.

Using operator->

I've written a simple container template class to contain a single
value. This emits a signal when the value is changed (it's used as a
notifier of changes), and listeners can connect to its changed signal.

i.e. field<int> i(2);
i = 4; // field<int>::m_value = 4; changed signal is emitted.

Currently, the contained value may be accessed via get_value() and
set_value() methods, and for ease of use, operator= and some type
conversions are provided. However, accessing a member function
requires a call to get_value(), and I'd like to overload operator->
and operator* to allow access. Ideally, I'd like a const version
(changes to the value are not allowed) and a non-const version, which
allows changes and emits a signal. However, I can't see that this is
possible (condensed for brevity):

template<typename T>
class field {
private:
value_type m_value;
SigC::Signal0<void> m_signal_changed; // libsigc++ signal type.
public:
typedef T value_type;

field(): m_value() {}
field(const value_type& value): m_value(value) {}
field(const field<value_type>& rhs): m_value(rhs.m_value),
m_signal_changed() {}
virtual ~field() {}

value_type& get_value() { return m_value; }
const value_type& get_value() const { return m_value; }

void set_value(const value_type& value)
{ m_value = value; m_signal_changed.emit(); }

field<value_type>& operator = (const field<value_type>& rhs)
{ set_value(rhs.m_value); return *this; }

field<value_type>& operator = (const value_type& rhs)
{ set_value(rhs); return *this; }

operator const value_type& () const { return m_value; }

SigC::Signal0<void>& signal_changed() { return m_signal_changed; }
}; // class field

If I provide a method like this:

const value_type *operator -> () { return &m_value; }

this is OK, but for the non-const version, I want to do this:

value_type *operator -> () { return &m_value; m_signal_changed() }

i.e. I want to emit the changed signal /after/ the caller has got the
pointer, used the method/member chosen and finished. If I emit the
signal before, the change won't yet have happened. However, I need to
return the pointer, so this is obviously impossible.

In addition, I'd like to make the const version the default (if a
const method is called from a non-const pointer), if possible, so that
the changed signal is only emitted on a genuine state change.

Are either of these possible using standard C++? If not, could anyone
suggest a different design to achieve the goal (signal emission after
value change)?
Many thanks,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
Jul 22 '05 #1
5 2100


Roger Leigh wrote:
i.e. I want to emit the changed signal /after/ the caller has got the
pointer, used the method/member chosen and finished. If I emit the
signal before, the change won't yet have happened. However, I need to
return the pointer, so this is obviously impossible.

In addition, I'd like to make the const version the default (if a
const method is called from a non-const pointer), if possible, so that
the changed signal is only emitted on a genuine state change.

Are either of these possible using standard C++? If not, could anyone
suggest a different design to achieve the goal (signal emission after
value change)?


You can't make the compiler use the const version of a function that is
overloaded on const alone i.e., the non-const method will always be
called on non-const objects. You have to differentiate the functions by
name i.e, rename non-const version of operator->() to be something like
get_value_to_change(). The long name encourages use of const values.

If you want to broadcast changes after the modification then you'll need
to use a set method and abandon the operator-> idea.

Jul 22 '05 #2
Roger Leigh wrote:
I've written a simple container template class to contain a single
value. This emits a signal when the value is changed (it's used as a
notifier of changes), and listeners can connect to its changed signal.

i.e. field<int> i(2);
i = 4; // field<int>::m_value = 4; changed signal is emitted.

Currently, the contained value may be accessed via get_value() and
set_value() methods, and for ease of use, operator= and some type
conversions are provided. However, accessing a member function
requires a call to get_value(), and I'd like to overload operator->
and operator* to allow access. Ideally, I'd like a const version
(changes to the value are not allowed) and a non-const version, which
allows changes and emits a signal. However, I can't see that this is
possible (condensed for brevity):

template<typename T>
class field {
private:
value_type m_value;
SigC::Signal0<void> m_signal_changed; // libsigc++ signal type.
public:
typedef T value_type; This typedef needs to go before the line (value_type m_value).

field(): m_value() {}
field(const value_type& value): m_value(value) {}
field(const field<value_type>& rhs): m_value(rhs.m_value),
m_signal_changed() {}
virtual ~field() {}

Are you not risking the value being changed and not having a signal
emitted with the following method. value_type& get_value() { return m_value; }

const value_type& get_value() const { return m_value; }

void set_value(const value_type& value)
{ m_value = value; m_signal_changed.emit(); }

field<value_type>& operator = (const field<value_type>& rhs)
{ set_value(rhs.m_value); return *this; }

field<value_type>& operator = (const value_type& rhs)
{ set_value(rhs); return *this; }

operator const value_type& () const { return m_value; }

SigC::Signal0<void>& signal_changed() { return m_signal_changed; }
}; // class field

If I provide a method like this:

const value_type *operator -> () { return &m_value; }

this is OK, but for the non-const version, I want to do this:

value_type *operator -> () { return &m_value; m_signal_changed() }

i.e. I want to emit the changed signal /after/ the caller has got the
pointer, used the method/member chosen and finished. If I emit the
signal before, the change won't yet have happened. However, I need to
return the pointer, so this is obviously impossible.

In addition, I'd like to make the const version the default (if a
const method is called from a non-const pointer), if possible, so that
the changed signal is only emitted on a genuine state change.

Are either of these possible using standard C++? If not, could anyone
suggest a different design to achieve the goal (signal emission after
value change)?

I am not sure I completely understood what you want but I will try. Are
you wanted to provide an operator-> for class field so that if T is a
structure you can access the individual fields? If so I don't think you
will be able to do that.

Michael Mellor
Jul 22 '05 #3
Michael Mellor <news-at-@michaelmellor-dot-.com> writes:
Roger Leigh wrote:
template<typename T>
class field {
private:
value_type m_value;
SigC::Signal0<void> m_signal_changed; // libsigc++ signal type.
public:
typedef T value_type; This typedef needs to go before the line (value_type m_value).


For what reason? Is this just a style issue? (Maybe this is just the C
programmer in me declaring everything before it's used?)
field(): m_value() {}
field(const value_type& value): m_value(value) {}
field(const field<value_type>& rhs): m_value(rhs.m_value),
m_signal_changed() {}
virtual ~field() {}


Are you not risking the value being changed and not having a signal
emitted with the following method.
value_type& get_value() { return m_value; }
Yes, since this is the only possible way to call non-const methods in
contained compounds. If you call this, you need to manually emit the
changed signal (field<T>::signal_changed().emit()).
const value_type& get_value() const { return m_value; }
void set_value(const value_type& value)
{ m_value = value; m_signal_changed.emit(); }
field<value_type>& operator = (const field<value_type>& rhs)
{ set_value(rhs.m_value); return *this; }
field<value_type>& operator = (const value_type& rhs)
{ set_value(rhs); return *this; }
operator const value_type& () const { return m_value; }
SigC::Signal0<void>& signal_changed() { return m_signal_changed;
}
}; // class field
If I provide a method like this:
const value_type *operator -> () { return &m_value; }
this is OK, but for the non-const version, I want to do this:
value_type *operator -> () { return &m_value; m_signal_changed()
}
i.e. I want to emit the changed signal /after/ the caller has got the
pointer, used the method/member chosen and finished. If I emit the
signal before, the change won't yet have happened. However, I need to
return the pointer, so this is obviously impossible.
In addition, I'd like to make the const version the default (if a
const method is called from a non-const pointer), if possible, so that
the changed signal is only emitted on a genuine state change.
Are either of these possible using standard C++? If not, could
anyone
suggest a different design to achieve the goal (signal emission after
value change)?

I am not sure I completely understood what you want but I will
try. Are you wanted to provide an operator-> for class field so that
if T is a structure you can access the individual fields? If so I
don't think you will be able to do that.


This is exactly what I want to do, and I agree with your conclusions.
What I've done is just provide an "operator -> () const", so it's
effectively read-only.

I've found a solution for non-const methods: If the contained class
uses the same signal mechanism as the field class (SigC++), I can
connect the changed signal of the contained class to the changed
signal of the field contained, so that the signal cascades, and I get
the behaviour I want. That is, I listen to the changed notification
and then notify my own listeners. This is useful, since it can nest
arbitrarily deeply for complex contained data structures.
Many thanks to you (and lilburne) for increasing my understanding!
Regards,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
Jul 22 '05 #4
Roger Leigh wrote:
Michael Mellor <news-at-@michaelmellor-dot-.com> writes:

Roger Leigh wrote:


template<typename T>
class field {
private:
value_type m_value;
SigC::Signal0<void> m_signal_changed; // libsigc++ signal type.
public:
typedef T value_type;


This typedef needs to go before the line (value_type m_value).

For what reason? Is this just a style issue? (Maybe this is just the C
programmer in me declaring everything before it's used?)

What compiler do you use that allows a type to be used before the typedef?
I get:

$ g++ -Wall -pedantic c.cc
c.cc:4: error: 'value_type' is used as a type, but is not defined as a type.

and

"ComeauTest.c", line 4: error: identifier "value_type" is undefined
value_type m_value;

Michael Mellor
Jul 22 '05 #5
Michael Mellor <news-at-@michaelmellor-dot-.com> writes:
Roger Leigh wrote:
Michael Mellor <news-at-@michaelmellor-dot-.com> writes:
Roger Leigh wrote:

template<typename T>
class field {
private:
value_type m_value;
SigC::Signal0<void> m_signal_changed; // libsigc++ signal type.
public:
typedef T value_type;

This typedef needs to go before the line (value_type m_value).

For what reason? Is this just a style issue? (Maybe this is just
the C
programmer in me declaring everything before it's used?)

What compiler do you use that allows a type to be used before the typedef?
I get:

$ g++ -Wall -pedantic c.cc
c.cc:4: error: 'value_type' is used as a type, but is not defined as a type.

and

"ComeauTest.c", line 4: error: identifier "value_type" is undefined
value_type m_value;


My apologies--I moved the private part of the class to the top in my
posting to make the problem clearer. It's actually right at the
bottom. I'm using GCC 3.3.3.

The full class (licence boilerplate stripped) is:
// database field container -*- C++ -*-
#ifndef PQXX_OBJECT_FIELD_H
#define PQXX_OBJECT_FIELD_H

#include <sigc++/signal.h>

namespace pqxxobject
{
/**
* Database field template class.
* This class is used to represent a single field in a row of a
* table. This is a single value belonging to a column in a row,
* rather than the whole column.
*
* As well as storing value, the class has the ability to emit
* signals when the field value is changed. Listeners (e.g. user
* interface widgets) may connect to the signal and will receive
* notification of changes as they occur.
*/
template<typename T>
class field
{
public:
typedef T value_type;

/// The constructor.
field():
m_value()
{}

/// The constructor.
field(const value_type& value):
m_value(value)
{}

/// The copy constructor.
field(const field<value_type>& rhs):
m_value(rhs.m_value),
m_signal_changed()
{}

virtual ~field()
{}

/// Access member functions.
const value_type *operator -> () const
{
return &m_value;
}

const value_type& operator * () const
{
return m_value;
}

/// Overloaded assignment operator.
field<value_type>& operator = (const field<value_type>& rhs)
{
set_value(rhs.m_value);
return *this;
}

/// Overloaded assignment operator.
field<value_type>& operator = (const value_type& rhs)
{
set_value(rhs);
return *this;
}

/// Conversion operator.
operator const value_type& () const
{
return m_value;
}

/**
* Get the contained value by reference.
* @returns a reference to the value.
*/
value_type& get_value()
{
return m_value;
}

/**
* Get the contained value by constant reference.
* @returns a constant reference to the value.
*/
const value_type& get_value() const
{
return m_value;
}

/**
* Set the contained value.
* @param value the value to set.
*/
void set_value(const value_type& value)
{
m_value = value;
m_signal_changed.emit();
}

/**
* Signal emitted on value change.
* @returns the signal.
*
* For example:
* @code
* field<int> col;
* someclass listener;
* col.signal_changed().connect
* ( SigC::slot(listener, &someclass::on_col_changed() );
* @endcode
* i.e. a class method (listener.on_col_changed()) will be called
* when the value is changed.
*/
SigC::Signal0<void>& signal_changed()
{
return m_signal_changed;
}

private:
/// The contained value.
value_type m_value;
/// The changed signal.
SigC::Signal0<void> m_signal_changed;

}; // class field

}; // namespace pqxxobject

#endif // PQXX_OBJECT_FIELD_H
--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
Jul 22 '05 #6

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

Similar topics

8
by: Douglas | last post by:
**** Post for FREE via your newsreader at post.usenet.com **** Hello, The following code does not compile if line 3 is uncommented "using namespace std". I do not understand it. Could...
1
by: Saeed Amrollahi | last post by:
Dear All C++ Programmers Hello I am Saeed Amrollahi. I am a software engineer in Tehran Sewerage Company. I try to use std::map and map::find member function. I use Visual Studio .NET. my...
2
by: Tony Johansson | last post by:
Hello Experts! I have one class template here called Handle and one concrete class called Point. At the bottom is the main program and the class template definitions for Handle. This program...
10
by: Tony Johansson | last post by:
Hello Experts!! This class template and main works perfectly fine. I have this class template called Handle that has a pointer declared as T* body; As you can see I have a reference counter in...
14
by: Craig O'Shannessy | last post by:
Hi all, Just thought I'd mention that I really think this problem needs to be fixed. I I'm patching the 7.4RC1 JDBC drivers as we speak due to this optimiser bug, and it's the third time...
13
by: kamaraj80 | last post by:
Hi I am using the std:: map as following. typedef struct _SeatRowCols { long nSeatRow; unsigned char ucSeatLetter; }SeatRowCols; typedef struct _NetData
0
by: Mona | last post by:
Newbie question - I am a newbie to c++ and stl maps. My question is based onSystemC which is a specialized C++ hardware programming language. I am trying to create a map with key of type sc_lv<22>...
7
by: yodadbl07 | last post by:
hey im trying to write a class of polynomials using a linked list. But I am getting an error at run time with my Polynomial* getNext() function. The error says access violation reading location. Im...
2
by: Bharath | last post by:
Hello All, Can you please let me know if we can do pointer arthrmetic using operator overloading? If not, can you please explain why it's not supported by compiler? I tried below e.g. which was...
15
by: aaragon | last post by:
Hello, does anyone have a clue about this error? and how to solve it? It seems to be trivial to me, but not for the compiler. I'm using g++ 4.2 on an Ubuntu Linux system: // main() .......
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: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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
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...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

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.