Detecting member function constness

Q

Querejeto

Hello:

Is it possible to detect programmatically the constness of a member
function when it is called?

That is, I would like to see a generic implementation (i.e. it does not
depend on the class Base) of the createInstance function below that
produces the output:

Output:
a const method was called.
a non const method was called.

Code:
class Base {
public:
void constMethod() const {
}
void nonConstMethod() {
}
};

void main() {
Base &base = createInstance<Base>();
base.constMethod();
base.nonConstMethod();
}


Thanks:
Querejeto
 
G

Gianni Mariani

Querejeto said:
Hello:

Is it possible to detect programmatically the constness of a member
function when it is called?

That is, I would like to see a generic implementation (i.e. it does not
depend on the class Base) of the createInstance function below that
produces the output:

Output:
a const method was called.
a non const method was called.

Like so ?

struct A
{
bool IsConst() const
{
return true;
}

bool IsConst()
{
return false;
}

};

#include <iostream>

int main()
{

A a;
const A & ac = a;

std::cout << a.IsConst() << "\n";
std::cout << ac.IsConst() << "\n";

}
 
A

Alf P. Steinbach

* Querejeto:
Is it possible to detect programmatically the constness of a member
function when it is called?

That is, I would like to see a generic implementation (i.e. it does not
depend on the class Base) of the createInstance function below

You forgot to show that function.

that produces the output:

Output:
a const method was called.
a non const method was called.

Code:
class Base {
public:
void constMethod() const {
}
void nonConstMethod() {
}
};

The member functions need to be virtual if they're to be overridden in
derived classes.

void main() {

Not valid.

Base &base = createInstance<Base>();

Not valid. Perhaps you meant

base.constMethod();
base.nonConstMethod();
}

The question doesn't make sense.
 
Q

Querejeto

Alf said:
* Querejeto:

You forgot to show that function.

The function call is in the code snippet that I presented. It is the
first line of the main method. Too bad I could not highlight it to make
it more clear. A prototype would be, I guess:

The member functions need to be virtual if they're to be overridden in
derived classes.

Agree. Assume they are virtual.
Not valid.

why is that prototype not valid?
Not valid. Perhaps you meant

Base* base = createInstance<Base>();

Why are you requiring the method to return a pointer? I don't quite see
why a reference won't do. In fact, I could argue that it conforms to
the standard that references are always valid, while pointers could be
NULL.
The question doesn't make sense.

To give you a little bit of more context of what I am trying to find
out: I would like to think of the class Base as a plain business class
(I guess Java programmers like to call it POJO: Plain Old Java Object)
that knows nothing of how it is used.

If clients so desire, they could attach extra functionality to it, like
for example: clients may want to log the object state after a non-const
method is called, or clients may want the object to notify observers
that it state changed, etc.

That sounds like there are cross-cutting concern that I would like to
extract from the class implementation, instead of inheriting
functionality from multiple classes (which seems intrusive to me) or
applying policies, which is also code that tends to "contaminate" the
pure business logic on the class Base.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

I apologize in advance if my posting does not conform to the standard.
I am an occasional user of newsgroups.
 
A

Alf P. Steinbach

* Querejeto:
why is that prototype not valid?

Because the standard says so. It's not valid for C, not for C++, and has
never been valid. The result type of 'main' must be 'int'.

Why are you requiring the method to return a pointer? I don't quite see
why a reference won't do. In fact, I could argue that it conforms to
the standard that references are always valid, while pointers could be
NULL.

OK, with the prototype & explanation you now supplied (snipped) it's
technically valid, sorry.

That sounds like there are cross-cutting concern that I would like to
extract from the class implementation

For general pre-call actions all you need is an ordinary smart-pointer
class. For general post-call actions the smart-pointer operator-> needs to
itself return a smart-pointer, where that operator-> result smart-pointer's
destructor (or a data member's destructor) does the post-call action.
However, while this works for simple logging, synchronization etc. you
cannot detect which member function is called because operator-> isn't told.

To do things on a per-member-function basis you need to use a wrapper that
offers the same external interface as Base, and forwards all calls to Base.

Such wrappers can be generated automatically by tools (use Google, perhaps
first to find the acronym for cross-cutting things, I always forget... ah,
aspect-oriented, first relevant hit and two links further, <url:
http://aosd.net/wiki/index.php?title=Tools_for_Developers>), or they can be
written "by hand"; in your case it's as simple as

class Derived: public Base
{
void constMethod() const
{
Logger log( whatever );
Base::constMethod();
}

void nonConstMethod()
{
Logger log( whatever );
Base::nonConstMethod();
}
};

where the constructor & destructor of Logger, which you must define to your
needs, does the logging work; here there's no "detection" of const or
non-const member function, but that information can be hardwired... ;-)

It's also possible to use more platform/compiler-dependent techniques that
within the constraint of a given platform are more general, e.g. COM-object
interceptors, but I'd advice against it.
 
Q

Querejeto

Alf said:
For general pre-call actions all you need is an ordinary smart-pointer
class. For general post-call actions the smart-pointer operator-> needs to
itself return a smart-pointer, where that operator-> result smart-pointer's
destructor (or a data member's destructor) does the post-call action.
However, while this works for simple logging, synchronization etc. you
cannot detect which member function is called because operator-> isn't told.

I believe this is exactly what I was looking for. I wonder if the
operator -> could tell whether the function being called was const or
not.

For example, suppose that my object is a subject (as in the
subject/observer pattern). If I want to notify its observers after
executing every non-const function in my business object, it would be
great if the smart pointer could tell whether the function being called
was const or not. That way I could inject the call to notify() at the
smart pointer abstraction level and remove the duplication of having to
do it on every non-const function on my business object.
 
A

Alf P. Steinbach

* Querejeto:
I believe this is exactly what I was looking for. I wonder if the
operator -> could tell whether the function being called was const or
not.

operator-> isn't told which member function, or even if this is a member
function call, which means it cannot do the detection. However, the client
code presumably knows, and can select one of two ways of calling the
function, e.g. like p->foo() versus p.modify()->bar(), and the smart-pointer
can then enforce at compile time that the const way, p->foo(), is not used
to call a non-const function, but AFAICS the opposite can not be enforced.
I think this is rather kludgy and non-transparent compared to a wrapper --
check out the aspect-oriented programming tools, there must be a
wrapper-generator there, somewhere -- but it's your choice.
 

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
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top