multipleinterfaces
multipleinterfaces

Reputation: 9163

How do I retrieve the type of the base class in C++?

For this particular project, I am not able to use C++11 features (e.g. decltype) because the compiler does not yet support them. I need to be able to provide the current class as a template parameter, preferably within a macro without an argument (see below), without dressing up the class declaration or hiding curly braces, etc.

class Foo: private Bar<Foo> {
   MAGIC //expands to using Bar<Foo>::Baz; and some others
   public:
      void otherFunction();
      //... the rest of the class
};

Ideally, I'd like this to work very much like Qt's Q_OBJECT macro, but without introducing another pre-compile step and associated generated classes. typeid might be useful at runtime, but my goal is to accomplish all of this at build.

How do I write the MAGIC macro so that I don't need to repeat the class name each time?

Upvotes: 10

Views: 268

Answers (4)

Simon Kraemer
Simon Kraemer

Reputation: 5670

You could use a "proxy"(?) struct for Building up the inheritance:

template <typename S>
struct Base : public S{ //always public, access is restricted by inheriting Base properly
    using super = S;
};

Usage would be as follows:

#include <iostream>

template <typename S>
struct Base : public S { 
    using super = S;
};

template <typename T>
class Bar
{
public:
    virtual void f() { std::cout << "Bar" << std::endl;  }
};

class Foo : private Base<Bar<int>>
{
public:
    virtual void f() 
    { 
        std::cout << "Foo";
        super::f();  //Calls Bar<int>::f()
    }
};

class Fii : private Base<Foo>
{
public:
    virtual void f() 
    {
        std::cout << "Fii";  
        super::f(); //Calls Foo::f()
    }
};


int main()
{
    Fii fii;
    fii.f(); //Print "FiiFooBar"
    return 0;
}

Upvotes: 0

Ryan Haining
Ryan Haining

Reputation: 36782

If you really don't care about formatting or writing a maintenance headache you can do this without repeating the type by having the macro take the type argument:

#define MAGIC(BASE) \
BASE { \
    using BASE::baz;

class Sub : private MAGIC(Base<Foo>)

  public:
    void otherFunction();
};

but this makes me feel pretty bad about myself

Upvotes: 0

galinette
galinette

Reputation: 9292

What about:

template<typename T>
class Base
{
protected:
    typedef Base<T> MagicBaseType;
    namespace Baz { }
};

class Derived1 : private Base<Derived1>
{
    using MagicBaseType::Baz;
}


class Derived1 : private Base<Derived2>
{
    using MagicBaseType::Baz;
}

or, if you can't modify the Base definition, using templates and multiple inheritance

template<typename T>
class Base
{
protected:
    namespace Baz { }
};

template<typename T>
class DerivedTemplate : public T
{
protected:
    typedef typename T BaseType;
}

class Derived : public Base<Derived>, public DerivedTemplate<Base<Derived>>
{
using BaseType::Baz;
}

Upvotes: 1

R Sahu
R Sahu

Reputation: 206557

I don't think there is any language supported mechanism to extract the base type from a class. You can use:

Option 1

class Foo: private Bar<Foo> {

#define BASE_TYPE Bar<Foo>
   // Use BASE_TYPE in MAGIC
   MAGIC //expands to using Bar<Foo>::Baz; and some others
#undef BASE_TYPE

   public:
      void otherFunction();
      //... the rest of the class
};

Option 2

class Foo: private Bar<Foo> {

    typedef Bar<Foo> BASE_TYPE;

   // Use BASE_TYPE in MAGIC
   MAGIC //expands to using Bar<Foo>::Baz; and some others

   public:
      void otherFunction();
      //... the rest of the class
};

Upvotes: 0

Related Questions