Bound member functions
Hi Everybody,
I've posted on the subject of bound member functions before, proposing a
library solution to address the issue, but a recent post by Matthew
Elkins made me think about the expressions:
obj.*func
ptr->*func
where func is a member function. All we currently know is that:
1) The result is a function of the type specified by the second operand
(see 5.5/2 and 5.5/3).
2) The result can be used only as the operand for the function call
operator () (see 5.5/6)
I find the choice of the word "function" in 5.5/2 and 5.5/3 very fishy,
but let's ignore that.
Now, 5.5/6, makes this code
auto bound_func = obj.*func;
bound_func();
illegal, however I believe a lot of people would agree with me that it
would be a wonderful thing to have in the language.
I do believe that there were very good reasons for having the
restriction in 5.5/6 back in C++99, although I ignore them. My question
is: are those reasons still good in 2007? We now know much more about
compiler technology, so maybe those reasons are no longer an impediment.
I mean, a bound member function can be implemented with just two
pointers! In fact, the implementation might even be simpler than a
pointer-to-member-function, because the resolution of virtual functions
and inheritance can be performed at the bounding site rather than at the
call site. Moreover, if expression on the right hand side is of the form
&C::func, the compiler might even be able to resolve the binding at
compile time without creating the pointer-to-member.
One possible reason that may have made obj.*func difficult to treat as a
callable object (rather than a "function") is that it's impossible to
describe its type with the C++ declarator syntax. However, that's no
longer an issue! The types of those expressions can be very simply
described in C+0x with:
decltype(obj.*func)
decltype(ptr->*func)
Of course, by using auto, we don't even need to use declspec.
Summarizing, I am suggesting that obj.*func and ptr->*func should be
objects (not functions) whose type T is unspecified, with:
1) T is a literal type: this would allow obj.*func to be a constant
expression whenever obj and func are constant expressions
2) T has no default constructor: the only way to get an object of type T
is by an expression involving .* or ->* or by copying an existing object
3) if t is an instance of T initialized with the expression obj.*func
(resp. ptr->*func), then the expression
t(t1, t2, ..., tN)
invokes the member function func on object obj (resp. *ptr), with
parameters t1, t2, ... tN.
In order to avoid object lifetime issues while still allowing the
resolution of the bound function at the binding site, it might be enough
to say that if the dynamic type of the object at moment of invoking the
function differs from the dynamic type of the object at moment of
binding, then the behaviour is undefined.
Is there something terribly obvious that I'm missing? I know that it's
getting very late for new proposals, but if I were to write a formal
one, do you think it might stand a chance of being considered?
Thanks in advance,
Ganesh
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]