DiscoStu
DiscoStu

Reputation: 569

Simplifying an interface declaration the C++03 way

As a way to reduce the busy work of copy/pasting the same code, I turned to the dark side and used a macro to do it for me.

Keep in mind the production code this is from is much larger and the task much more painful without macros like this to help. Specifically, it's a mix of static and virtual functions driven by a single string.

Now I know macros can get you into trouble, and using them this way is pretty 'stinky', so I want something better, but I'm having trouble coming up with something as easy and concise as this:

#define LAZY(name)\
   static const char * identify() { return name; }\
   virtual const char * getName() { return identify(); }

class A{
public:
   LAZY("class A")

   void foo(){
      std::cout << getName() << std::endl;
   }
};

class B: public A{
public:
   LAZY("class B")
};

std::string somevar( B::identify() );

int main(void){
   B b1;
   B.foo();
}

Some of the other approachs I took (and why they failed), are below:

template<class T>
class Base{
public:
   virtual const char * getName(){ return T::identify(); }

   // All other functions driven by string. IE:
   static void register(){ someFactory::reg( T::identify() ); }
   virtual unsigned int getHash(){ return someHashFoo( T::identify() ); }
};

class A: public Base<A> {
public:
   static const char * idenfity(){ return "class A"; }

   void foo(){ std::cout << getname() << std::endl; }
};

class B: public A, public Base<B> {
  // Conflict due to multi-inheritance.
};

Another failed approach due to wasting memory per instance, and a little complex:

class FaceBase{
public:
   virtual const char * getName() =0;
};

template<class T>
class ImplBase: public FaceBase {
public:
   virtual const char * getName(){ return T::identify(); }
};

class A{
public:
   FaceBase & common;

   static const char * identify(){ return "class A"; }

   A(): common(ImplBase<A>()){}

   virtual void foo(){ std::cout << common.getName() << std::endl; }
};

class B: public A{
   static const char * identify(){ return "class B"; }

   B(){ common = ImplBase<B>(); }
};

Upvotes: 3

Views: 120

Answers (1)

Sebastian Redl
Sebastian Redl

Reputation: 71989

You didn't actually ask any question, but under the assumption that it is, "How can I do this in a clean way without macros?", and further assuming that the "much larger" task you're referring to is a full custom RTTI system, the answer is, "You can't."

Every big project that does this kind of thing that I know of (MFC, Qt, LLVM) does one of these:

  • Use macros. (MFC and to some extent Qt)
  • Use a custom code generator. (Qt and to some extent LLVM)
  • Write the boilerplate code. (LLVM)

Upvotes: 6

Related Questions