From 1851650768964514934
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,28671cb074853115
X-Google-Attributes: gidf78e5,public
From: James Kanze <james-albert.kanze@vx.cit.alcatel.fr>
Subject: Re: offsetof macro, can it be used in non-trivial classes?
Date: 1997/01/06
Message-ID: <rf5afqn6kbj.fsf@vx.cit.alcatel.fr>#1/1
X-Deja-AN: 208125703
references: <01bbead3$6fbf55f0$c07797cd@hacknowledge>
x-original-date: 06 Jan 1997 13:48:32 +0100
organization: -
x-auth: PGPMoose V1.1 PGP comp.std.c++
newsgroups: comp.std.c++
originator: austern@isolde.mti.sgi.com
x-mailer: Gnus v5.3/Emacs 19.34


Richard Krehbiel <rich@kastle.com> writes:

|>  Here's a paraphrase of the code I'm using now.  I like it because the
|>  callback class and derivatives have no (well, the fewest possible
|>  number of) data members.  I'd like it to be standard-conforming, but I
|>  prefer the minimum data size (I have *lots* of things with callbacks).

I think that what you actually need is inheritance, possibly private.

|>  class callback
|>  {
|>  public:
|>  	virtual void invoke() = 0;
|>  	static void register(callback&, int);
|>  	static void run();
|>  };
|>  
|>  void callback::register(callback &cb, int event)
|>  {
|>  	// add cb to list of callbacks indexed by event
|>  }
|>  
|>  void callback::run()
|>  {
|>  	callback *cb;
|>  	for(;;)
|>  	{
|>  		// (get next event and translate into appropriate cb)
|>  		cb->invoke();
|>  	}
|>  }
|>  
|>  class specialized_callback_1 : public callback
|>  {
|>  public:
|>  	virtual void invoke();

    	virtual void     invoke_1() = 0 ;

|>  }
|>  
|>  class specialized_callback_2 : public callback
|>  {
|>  public:
|>  	virtual void invoke();

    	virtual void     invoke_2() = 0 ;

|>  }
|>  
|>  class thing

    class thing
    	: private specialized_callback_1
    	, private specialized_callback_2

|>  {
|>  public:
|>  	thing();
|>  	friend class specialized_callback_1;
|>  	friend class specialized_callback_2;
|>  	specialized_callback_1 cb1;
|>  	specialized_callback_2 cb2;

Previous four lines not needed.

|>  private:
|>  	void invoke_1();
|>  	void invoke_2();
|>  };
|>  
|>  thing::thing()
|>  {
|>  	callback::register(cb1, 1);
|>  	callback::register(cb2, 2);

  	callback::register( (specialized_callback_1*)( this ) , 1) ;
  	callback::register( (specialized_callback_2*)( this ) , 2) ;

(Actually, I think I'd put the registration in the constructors of the
specialized callback's.)

|>  }
|>  
|>  // Here's when I use offsetof
|>  
|>  #define CONTAINER(ptr,type,member)  (type *) \
|>  									((char *)(ptr) - offsetof(type,member))
|>  
|>  void specialized_callback_1::invoke()
|>  {
|>  	thing *tp = CONTAINER(this, thing, cb1);
|>  	tp->invoke_1();

Instead of the previous two lines:

    	invoke_1() ;

|>  }
|>  
|>  void specialized_callback_2::invoke()
|>  {
|>  	thing *tp = CONTAINER(this, thing, cb2);
|>  	tp->invoke_2();

Instead of the previous two lines:

    	invoke_2() ;

|>  }

This is, after all, what inheritance is all about.

-- 
James Kanze         home:     kanze@gabi-soft.fr        +33 (0)3 88 14 49 00
                    office:   kanze@vx.cit.alcatel.fr   +33 (0)1 69 63 14 54
GABI Software, Sarl., 8 rue des Francs Bourgeois, F-67000 Strasbourg, France
	      -- Conseils en informatique industrielle --
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your 
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu 
]



