Home > Coding, Rants & Opinions > Things I’d love in C++

Things I’d love in C++

Functional Morphing: Callbacks / Delegates

I’ve always found the C++ methods for implementing callback functions etc to be rather messy. It’s another victim of the reluctance of the C++ old-guard to accept the introduction of interfaces.

Look, I don’t want to allow user transformation of my objects, I want them to be fixed, set sizes. All I want to do is allow them to replace some of the functions.

class FixedSizedObject
{
  int i ;
  float j ;
  vector v ;
public:
  FixedSizedObject(const int i_, const float j_, const vector& v_)
    : i(i_), j(j_), v(v_)
  {}

public:
  virtual void onClose() ;
  virtual void onPaint() ;
} ;

This derivative is ok:

class ImplementedFSO : public FixedSizedObject
{
public:
  virtual void onClose() override ; // We implement our own.
} ;

But this variant breaks things:

class BrokenFSO : public FixedSizedObject
{
private:
  bool isInitialized ; // MERP! You changed the size.
} ;

Wrappers – without resorting to Macros or Templates

Polymorphism only allows for growing objects in one direction. If you want one object to extend another by prefixing the inset object, you can only do so by making the parent object a member.

class Data
{
  char name[64] ;
  size_t length ;
  float weight, height ;

public:
  Data(const char* const name_, const size_t length_, const float weight_, const float height_) ;
  // ...
} ;

This class extends Data by adding to the end of it:

class DataSuffix : public Data
{
  uint64_t recorded ;
  callback_t callbackId ;
} ;

Whereas this class wraps data by adding to the front of the structure in memory.
Downside: Not isa Data.

class DataWrapper
{
  uint64_t recorded ;
  callback_t callbackId ;
  Data data ;
} ;

Using multiple-inheritance to combine the two with the wrapper at the front.
Downside: no guarantees how the object will look in memory.

class Wrapper
{
  uint64_t recorded ;
  callback_t callbackId ;
} ;

class DataWrapperMulti : public Wrapper, public Data
{
};

Interfaces

So much in C++ could be done more efficiently and more cleanly if the language would provide a method for functions-only definitions.

We were cleaning up a certain API at work just recently, and a couple of use decided we were going to take a stab at replacing the old largely C-oriented API with a nice clean C++ replacement.

And then we realized: everything will have to #include the entire API header if we do things in terms of member functions.

// Version 1, the C way.
#include <sys/socket.h>
#include <string>
#include <vector>

// SocketType.h
class Socket
{
  // Oh hai, these are my innards, which require you #include
  // lots of stuff.
};

//////////////////////////////////////////////
// SocketAPI.h
// This is the one that most code will #include.

class Socket ;

//! Given a socket index, find the socket object.
//! Socket* socket = sockLookupSocket(socketId) ;
Socket* sockLookupSocket(socketid_t) ;

//! Given a socket index, set the 'appCustomData' field.
void sockSetCustomData(socketid_t, void* data) ;
// ...

To do this in C++ as member functions, you have to expose the whole damn object, or else mess about with partitioning your object into an impl and creating pass-thru functions for everything. Have I mentioned how much I hate the impl method?

// Version 2 - C++. Everyone has to include all of this crap.
#include <sys/socket.h>
#include <string> // The source of ALL evil
#include <vector>

class Socket
{
  // Oh hai, you can see my innards!
  // ... private stuff, for some reason at the top of the public #include.
public:
  //! Find a socket by it's index.
  //! Socket* socket = Socket::Lookup(socketId) ;
  //! But in order to do that, you have to #include the rest of Socket.
  static Socket* Lookup(socketid_t) ;

  //! Given a socket index, set the 'appCustomData' field.
  static void SetCustomData(socketid_t socketId, void* const data_)
  {
    Socket* const socket = Lookup(socketId) ;
    if ( socket != NULL )
      socket->setCustomData(data) ;
  }

private:
  // This function, that you can see here, is private. Don't read it!
  void setCustomData(void* const data_) { m_customData = data_) ;
} ;

Oh for a native-compiling C# :(

Categories: Coding, Rants & Opinions
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 183 other followers

%d bloggers like this: