Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #9264

Re: Fun with member-function pointers

From Andrey Tarasevich <andreytarasevich@hotmail.com>
Newsgroups comp.lang.c++
Subject Re: Fun with member-function pointers
Date 2011-08-23 18:43 -0700
Organization A noiseless patient Spider
Message-ID <j31kvb$iso$1@dont-email.me> (permalink)
References <9bg0ojFsapU1@mid.individual.net> <4e5351c3$0$6566$9b4e6d93@newsspool3.arcor-online.net>

Show all headers | View raw


On 8/23/2011 12:07 AM, Marcel Müller wrote:
>>
>> class tbase
>> {
>> public:
>>     tbase() : p(0)
>>     {
>>     }
>>     typedef  int (tbase::*HandlerPtr)(int);
>> protected:
>>     HandlerPtr p;
>> };
>> class test : tbase
>> {
>> public:
>>     test()
>>     {
>>        p  = static_cast<HandlerPtr>(&test::f);
>
> This is undefined behavior. It only happens to work as long as pointers
> to tbase and pointers to test are binary the same.

Absolutely incorrect. This cast is perfectly legal. This use of 
`static_cast` is explicitly allowed and supported by the language 
specification.

Actually, if this cast suffered from the problem you imply, it would 
simply be disallowed. C++ style casts were specifically introduced to 
outlaw straightforward hacks.

> To illustrate the point: change your code to (see below) and it will
> sadly fail.

No, the code you provided below also works perfectly fine, as it should. 
The only reason it might "fail" is the non-compliant compiler that 
attempts to save memory by using different pointer representation for 
different hierarchy types. Such compiler usually have an option to 
restore the proper behavior.

> I would like to have this pattern supported by the language too, but
> there is an important implementation issue.

This "pattern" has been supported by the language since the very first 
standard of C++.

> Any function of type HandlerPtr expects an object of type tbase* as this
> argument, while the function test::f expects an object of type test* as
> this argument. Normally when the tbase slice of test is accessed the
> compiler generates the required code to access the slice. But this time
> is the other way around (contravariance). The compiler converts test* to
> tbase* to call the function pointer which claims to need tbase*, but the
> function behind p expects test*. Ouch, who does the downcast?

The compiler does it. It is required to perform the downcast by the 
language standard. This downcast is in general case a non-trivial 
operation, which is why a correctly implemented pointer to member 
function has to carry some extra information with it (and which is why 
its size is generally larger than that of an ordinary pointer). This 
extra information is there specifically to allow the compiler to 
generate the code for proper run-time downcast.

> Also how should the compiler ensure that the this pointer used to invoke
> a function pointer of type HandlerPtr is of type test*.

It doesn't. It is your responsibility. If you attempt to access a member 
that doesn't really exist, the behavior is undefined.

> Member function pointers are not the solution of your problem. You
> should use an observer pattern instead.

They are. They are not developed very well, meaning that some pattern 
(like Observer) might indeed be a better solution. But your specific 
arguments against the pointer are based on totally incorrect premise.

> Member function pointers are the other way around. A pointer of type
> void(test::*)() can be used to call functions of type void(tbase::*)(),
> since every function that expects tbase* can also be invoked with test*.
> The compiler will handle the necessary conversion at each invocation of
> the function pointer. For this reason member function pointers are
> larger than one machine size word in general. The compiler usually adds
> offset information for this. (Things get even more complicated if tbase
> is a virtual base class of test.)

You are almost right. Member function pointers are indeed "the other way 
around". Member function pointers are contravariant. They support 
implicit conversion down the hierarchy, as well as they support an 
explicit conversion up the hierarchy. The latter is explicitly allowed 
by the specification of `static_cast`.

-- 
Best regards,
Andrey Tarasevich

Back to comp.lang.c++ | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Fun with member-function pointers "Default User" <defaultuserbr@yahoo.com> - 2011-08-22 16:41 -0500
  Re: Fun with member-function pointers Victor Bazarov <v.bazarov@comcast.invalid> - 2011-08-22 19:25 -0400
    Re: Fun with member-function pointers "Default User" <defaultuserbr@yahoo.com> - 2011-08-22 19:06 -0500
  Re: Fun with member-function pointers Juha Nieminen <nospam@thanks.invalid> - 2011-08-23 07:09 +0000
    Re: Fun with member-function pointers Victor Bazarov <v.bazarov@comcast.invalid> - 2011-08-23 08:04 -0400
      Re: Fun with member-function pointers Juha Nieminen <nospam@thanks.invalid> - 2011-08-23 13:34 +0000
        Re: Fun with member-function pointers Victor Bazarov <v.bazarov@comcast.invalid> - 2011-08-23 13:02 -0400
      Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-23 19:12 -0700
    Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-23 18:51 -0700
  Re: Fun with member-function pointers Marcel Müller <news.5.maazl@spamgourmet.com> - 2011-08-23 09:07 +0200
    Re: Fun with member-function pointers Juha Nieminen <nospam@thanks.invalid> - 2011-08-23 10:09 +0000
      Re: Fun with member-function pointers Marcel Müller <news.5.maazl@spamgourmet.com> - 2011-08-23 15:04 +0200
    Re: Fun with member-function pointers "Default User" <defaultuserbr@yahoo.com> - 2011-08-23 10:36 -0500
      Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-23 18:46 -0700
        Re: Fun with member-function pointers "Default User" <defaultuserbr@yahoo.com> - 2011-08-24 09:33 -0500
          Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-24 08:32 -0700
            Re: Fun with member-function pointers "Default User" <defaultuserbr@yahoo.com> - 2011-08-24 11:15 -0500
              Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-24 09:30 -0700
      Re: Fun with member-function pointers Marcel Müller <news.5.maazl@spamgourmet.com> - 2011-08-24 12:27 +0200
        Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-24 06:46 -0700
          Re: Fun with member-function pointers Marcel Müller <news.5.maazl@spamgourmet.org> - 2011-08-24 18:57 +0200
            Re: Fun with member-function pointers Paul <pchristor@yahoo.co.uk> - 2011-08-24 13:08 -0700
              Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-24 13:44 -0700
                Re: Fun with member-function pointers Paul <pchristor@yahoo.co.uk> - 2011-08-25 04:23 -0700
                Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-25 07:31 -0700
                Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-25 08:21 -0700
                Re: Fun with member-function pointers Paul <pchristor@yahoo.co.uk> - 2011-08-25 10:50 -0700
                Re: Fun with member-function pointers Leigh Johnston <leigh@i42.co.uk> - 2011-08-25 13:57 +0100
                Re: Fun with member-function pointers Leigh Johnston <leigh@i42.co.uk> - 2011-08-25 14:08 +0100
                Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-25 07:32 -0700
                Re: Fun with member-function pointers Leigh Johnston <leigh@i42.co.uk> - 2011-08-25 15:45 +0100
                Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-25 07:48 -0700
    Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-23 18:43 -0700
  Re: Fun with member-function pointers Paul <pchristor@yahoo.co.uk> - 2011-08-23 03:49 -0700
    Re: Fun with member-function pointers Paul <pchristor@yahoo.co.uk> - 2011-08-23 06:44 -0700
  Re: Fun with member-function pointers Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-08-23 18:28 -0700
  Re: Fun with member-function pointers Jeff Flinn <TriumphSprint2000@hotmail.com> - 2011-08-25 11:29 -0400

csiph-web