Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplifying an interface declaration the C++03 way

Tags:

c++

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>(); }
};
like image 483
DiscoStu Avatar asked Jan 27 '26 15:01

DiscoStu


1 Answers

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)
like image 132
Sebastian Redl Avatar answered Jan 30 '26 04:01

Sebastian Redl