17

Is there a way to build a typedef inside a type declaration to the declared (surrounding) type itself without stating the type's name?

Example:

class X
{
  public:
    typedef <fill in magic here> MyType;
  //...
};

Background: This seems silly on the first look. I need this because I build compile-time-reflection of my data classes using macros. So there is a macro inserted into the declaration of the data class which needs to deal with the type it is inserted into. So far I found working solutions for MSVC and g++ which both rely on what I think are flaws in the implementation. So they may not work on a newer version. Clang does not "eat" either of these solutions.

My current solution for MSVC defines a method and then takes it's address only by it's name and calls a small helper that "returns" the type of it's class. (Clang and g++ expect the full name of the method including it's class name).

My current solution for g++ defines a static method with return type std::remove_reference(decltype(*this)). (Clang and MSVC do not allow this in the static context).

I would absolutely prefer a standard conform solution but a special solution for clang would also be ok for the moment.

If nothing works I have to pass the class' name to the macro but I try to avoid this since I already have plenty of code using the macro.

EDIT: Adding a sample on how the reflection works (which may clarify what I need):

class X : public Y
{
  public:
    //.. constructor and such stuff...

    int a;
    double b;
    std::string c;

    CLASSHEAD(Y)
      FIELD(a)
      FIELD(b)
      FIELD(c)
    CLASSFOOT
};

CLASSHEAD is the macro that should define typedef. It is a VAR_ARGS macro where the arguments receive the base classes. As said: It is possible to give it the class' name as it's first argument (resulting in CLASSHEAD(X, Y) in the example). But I nearly cannot imagine that there is no solution to such a "simply" task as typedef'ing the surrounding type...

  • Actually, it is not clear to my why you can't just do `typedef X MyType;`, and then have the macros use `MyType`? – BoBTFish Jan 27 '16 at 10:07
  • So will all of the classes expected to use this mechanism inherit from the same base? (In which case I can reinstate my CRTP answer). – BoBTFish Jan 27 '16 at 10:25
  • 1
    The only reason I can think for needing this is in function signatures. Within the function itself, you would use `typedef std::remove_reference(decltype(*this))::type MyType;` as above. You could make those functions templates, then `static_assert(std::is_same::value);`. Not pretty, can't think of anything better. – BoBTFish Jan 27 '16 at 10:49
  • 1
    I am afraid to get standard compliant solution you must wait until new standard is ready with type reflection (in your case introspection). See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3814.html – PiotrNycz Feb 02 '16 at 13:53
  • 2
    Seems like the way to do this is to define a macro that creates the class declaration. The class name would be a parameter to the macro, and it will then emit the `public CLASSNAME MyType;` line. – Barmar Feb 02 '16 at 22:17
  • I work around this by putting in any class that needs this feature `typedef X self; typedef Y inherited;` at the top. – M.M Feb 03 '16 at 00:03
  • 1
    [Similar question](http://stackoverflow.com/questions/21143835/can-i-implement-an-autonomous-self-member-type-in-c) – chris Feb 03 '16 at 01:02
  • Just a remark: g++-5.2 does not accept the decltype "solution" in a static context. – Rumburak Feb 03 '16 at 21:02
  • Please do not deface your questions. – Brad Larson Feb 15 '16 at 19:20

3 Answers3

2

This doesn't exactly meet your specification, but I think its pretty close:

class X
{
//Stuff...

//Use Macros to add:
struct MyType;

//Use class closing macro to insert variable between class-ending brace and semicolon      


} TYPE_VAR;
//Perhaps add random stuff to TYPE_VAR name to avoid collisions, like __FILE__
struct decltype(TYPE_VAR)::MyType
{
    typedef decltype(TYPE_VAR) V;
};

Then access X's type using

X::MyType::V

For example, a simplified CLASSFOOT might look like this:

#define CLASSFOOT /*Your classfoot here*/ } TYPE_VAR; struct decltype(TYPE_VAR)::MyType {typedef decltype(TYPE_VAR) V;
//No }; at end on purpose- this will come from the class in which you placed CLASSFOOT

Is this good enough for your purposes?

Straw1239
  • 589
  • 2
  • 8
0

Since you are already using macros, you could use this solution https://stackoverflow.com/a/21143997/2173029

#define CLASS_WITH_MY_TYPE(ClassName) \ 
    class ClassName                   \
    {                                 \
       using MyType = ClassName;

And then use like

CLASS_WITH_MY_TYPE(X)
public:
  struct Y
  {
    using T = MyType;
  };
};

static_assert(std::is_same<X, typename X::Y::T>::value, "");

Marked as community wiki since @Chris mentioned the link and the original answer was posted by @Bartek Banachewicz

Community
  • 1
  • 1
Rumburak
  • 3,416
  • 16
  • 27
-3

Nohting works so using the class Name in the macro is the only working solution

mmmmmmmm
  • 15,269
  • 2
  • 30
  • 55