10

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?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
multipleinterfaces
  • 8,913
  • 4
  • 30
  • 34
  • This question seems to be the C++03 version of "[Can I implement an autonomous `self` member type in C++?](http://stackoverflow.com/q/21143835/560648)" – Lightness Races in Orbit Mar 04 '16 at 15:18
  • 1
    Mind if I change the title to *base clase*? *enclosing class* makes it sound like you are nesting and what the type off the outer class. – NathanOliver Mar 04 '16 at 15:20
  • The `self` question does look very similar, but it doesn't look like any of the proposed solutions work in C++03, as you noted. Certainly change the title if it will make it more clear. – multipleinterfaces Mar 04 '16 at 15:22
  • 2
    In C++ one has to ask *which baseclass?* – Peter - Reinstate Monica Mar 04 '16 at 15:31
  • And my 2 cents are: It's probably not possible; instead of strong-arming a macro system which was not designed for it, either run your code e.g. through a perl script; or find a different solution which uses C++ (e.g. use a unique int as template argument, not a typename). – Peter - Reinstate Monica Mar 04 '16 at 15:34
  • http://stackoverflow.com/questions/8709340/can-the-type-of-a-base-class-be-obtained-from-a-template-type-automatically – Simon Kraemer Mar 04 '16 at 15:46

4 Answers4

1

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;
}
galinette
  • 8,896
  • 2
  • 36
  • 87
0

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;
}
Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49
0

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
};
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

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

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174