11

I want to write a macro which, when expanded within a class, uses that class type (specifically, as template argument). Within class method, I can use this:

#define METHOD_MACRO int sample_method(void)const {\
    return template_struct<this_type<decltype(this)>::type>::index;}

(this_type is my struct, here it's equivalent to remove_pointer<remove_const<T>>)

But when I need class type outside of method (for typedef for class member pointer), this keyword isn't available; I've tried to use auto for some trick with deducing type, but no luck here. Classes in question are inherited from my class, if this can be of any help. I would like to avoid anyone using my macro having to write obligatory typdedef.

Any ideas?

Abstraction
  • 1,108
  • 11
  • 25
  • 2
    Use CRTP? Perhaps you can eliminate macros altogether... – n. m. could be an AI Oct 20 '15 at 07:53
  • This requires explicit effort from user, which I try to avoid as much as possible. Interesting idea, but not quite there. – Abstraction Oct 20 '15 at 07:57
  • 1
    @Abstraction Typing the name of your macro requires as much explicit effort from the user than inheriting from a class with CRTP :) – Drax Oct 20 '15 at 08:29
  • @Drax There still is a problem of overriding virtual functions, but yes, this is possible solution (and more elegant than requiring "typedef Class self" or the like). It just doesn't make much sense for a user - having to write class name twice like that. – Abstraction Oct 20 '15 at 08:47
  • @Petr - yes, it is the same. Didn't find it by search, my bad. Thanks for the help, though - even while your solution is compiler-dependent, this may be enough. – Abstraction Oct 20 '15 at 11:39

1 Answers1

10

You can use the following trick:

#define SELF \
    static auto helper() -> std::remove_reference<decltype(*this)>::type; \
    typedef decltype(helper()) self

struct A {
    SELF;
};

I declare a helper function using the auto return type, which allows me to use decltype(*this) as a return type, not knowing what is the class name. Then I can use decltype(helper()) to use the class type in the code. Note that the function has to be static, otherwise you can not use it in decltype. Also the function is just declared, not defined; this should not be a problem as you are not going to call it anyway. (You can add an empty body to it, but it will raise a warning that a function has no return. Still you may change the return type to be decltype(this) and return nullptr.)

You may then use the self typedef for further declarations, or just alter the macros to typedef not the class itself, but what you need to. Adjust it to suit your particular need.

UPD: This seems to be a non-standard behavior of GCC. For example, ICC does not allow this in static functions even in trailing return type.

Petr
  • 9,812
  • 1
  • 28
  • 52
  • 7
    Why can you use `this` in this context? – n. m. could be an AI Oct 20 '15 at 10:32
  • @n.m., why can't I? I am no expert in the standard, but my rough understanding is that `this` is just an implicit function parameter, and I can use function parameters in return type with `auto`. And it does work: http://coliru.stacked-crooked.com/a/9af8022707a13ff6 – Petr Oct 20 '15 at 10:39
  • 1
    @n.m., although I just though that it is indeed strange to have `this` in a `static` function. Was initially trying to make it as a non-static, added `static` to make `decltype(helper())` work, and did not realize that `decltype(*this)` might break. Anyway, it works. Don't say it is GCC's bug :) – Petr Oct 20 '15 at 10:40
  • 1
    @n.m., interesting, it seems that GCC allows to use `decltype(*this)` in _trailing return type_, but not in function body, and I can find no explanation on this. Will probably ask a separate question soon. – Petr Oct 20 '15 at 10:52
  • @n.m., OK, [this answer](http://stackoverflow.com/a/21148117/3216312) says it is specific to GCC, and, indeed, ICC rejects my code. In fact, this question seems to be duplicate of that one. – Petr Oct 20 '15 at 11:06
  • 3
    Yes, this looks like a gcc bug. – n. m. could be an AI Oct 20 '15 at 11:13
  • I don't see why this is a bug. Unless it's a feature the compiler "did it by accident" (this (kw) is defined in such a way that nothing broke when it was used like this) and it's in code that'll never run. There's also no legit meaning for such code that isn't this that's even conceivable (what else could it mean?) C++11 was gimped by needlessly strong rules - almost all of which were backtracked extremely quickly (eg constexpr); I get a new keyword (self) would cause hurt (and I wouldn't want that as I've probably got code making it a keyword would break) so decltype(*this) in type-contexts! – Alec Teal Dec 29 '18 at 14:10
  • The year is 2022 and it is allowed only on MSVC – vikAy Mar 11 '22 at 13:13