Reputation: 9163
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
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
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
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
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