[MUD-Dev] doesNotUnderstand behavior in C++ (was: Spoofs)

Eli Stevens listsub at wickedgrey.com
Fri Nov 30 15:50:42 New Zealand Daylight Time 2001


I am the necromancer![*]

Yes, this is old, but I have thought about the topic below a little
more, and I am pretty sure what I describe below is correct (I
haven't had the gumption to actually code it up though).  I
hesitated to send it at first, because I had just been reading
"Modern C++ Design" that weeek, and it was all still a bit
overwhelming.  I was wondering if anyone else with a little more
finesse in the area could comment on it, as I am considering using
something like it in the WGMud project.

Thanks...   :)

--<begin old draft of a post>--

----- Original Message -----
From: "Bobby Martin" <bobbymartin at hotmail.com>
To: <mud-dev at kanga.nu>
Sent: Thursday, September 27, 2001 6:00 PM
Subject: Re: [MUD-Dev] Spoofs

> Hmm, I consider myself to be something of a C++ guru, and I don't
> think that I buy this.  How do you make C++ emulate the
> doesNotUnderstand behavior of a Smalltalk object?  In SmallTalk,
> when you call a method on an object that doesn't implement that
> method, it calls the doesNotUnderstand method on that object with
> the actual method signature and parameters as arguments to the DNU
> method.  I don't see how you could do an equivalent in C++ without
> essentially writing a meta language.

I am somewhat new to the finer nuances of templates, but I believe
that what you describe can be accomplished by the following.  If I
am wrong, I apologize...  I am still digesting the first few
chapters of "Modern C++ Design."

  // start gratuitious C++
  
  class MessageType1
  {
  public:
      void Foo()
      {}
  }
  
  class Base
  {
  public:
      template<typename DoesNotUndertand>
      void ProcessMessage( DoesNotUnderstand msg )
      {
          // whatever is appropriate for not understanding a message
      }
  }
  
  class Handler : public Base
  {
  public:
      template<MessageType1>    // <-- you may be able to omit this line
  entirely
      void ProcessMessage( MessageType1 msg )
      {
          msg.Foo();
          return;
      }
  }
  
  // end C++
  
Now, if that qualifies as a meta language, OK.  :)

The Base ProcessMessage could have a compile time assertion, throw
an exception, silently fail, whatever.  If you wanted to ge extra
fancy, you could replace Base with a policy class for Handler, and
so each type of Handler could define on its own how to respond to
un-understood(?) messages.

If you need to pass pointers to Handlers around, and don't care how
they respond to unhandled messages, you could make an interface to
Handler, and subclass it with the actual template class (that way
you can call all the methods on Handler w/o knowing the concrete
type, which would include the policy class).

  // start the C++ again
  
  class ThrowExceptionPolicy
  {
  public:
      template<typename DoesNotUndertand>
      void ProcessMessage( DoesNotUnderstand msg )
      {
          // throw an exception
      }
  }
  
  class SilentlyIgnorePolicy
  {
  public:
      template<typename DoesNotUndertand>
      void ProcessMessage( DoesNotUnderstand msg )
      {
      }
  }
  
  class CompileTimeAssertionPolicy
  {
  public:
      template<typename DoesNotUndertand>
      void ProcessMessage( DoesNotUnderstand msg )
      {
          // make a compile time assertion (see Modern C++ Design),
          // or one of many other places, I would assume.
      }
  }
  
  template<class UnhandledMessagePolicy>
  class Handler : public UnhandledMessagePolicy, HandlerInterface
  {
  public:
      template<MessageType1>    // <-- you may be able to omit this line
  entirely
      void ProcessMessage( MessageType1 msg )
      {
          msg.Foo();
          return;
      }
  }
  
  int main()
  {
      Handler<SilentlyIgnorePolicy> h1;
      Handler<ThrowExceptionPolicy> h2;
  
      MessageType2 msg;
  
      h1.ProcessMessage( msg );  // will not do anything
      h2.ProcessMessage( msg );  // will throw an exception
  
      return 0;
  }
  
  // end C++

On a side note, I would like to point out (and hopefully invalidate
as an argument against X) is that anyone can produce bad, ugly and
evil code in any language X, weather or not language X encourages or
discourages the practice.  Lord knows I have.  ;) This tangent is
fairly interesting, but I would hate to see it dissolve into "Y
project was in X, and it had been beaten with the ugly stick so many
times the developers' mothers hated it."  
--<end draft>--

Ok, so that last paragraph only really applied in the context of the
thread at the time.  I still like it though.  Sue me.  :P

[*] - I resurrect dead threads.  ;)
Eli

--
Never use brute force in fighting an exponential.
      -- Andrei Alexandrescu, "Modern C++ Design"


_______________________________________________
MUD-Dev mailing list
MUD-Dev at kanga.nu
https://www.kanga.nu/lists/listinfo/mud-dev



More information about the MUD-Dev mailing list