1

Say there is a macro:

#define X(...) foo(__VA_ARGS__)

foo is defined as:

void foo(int a) {}
template<class T> 
void foo(int a, T& t) { std::cout<<a<<t.b; }

I'd like to check if X is called within a class or not. If it is called within a class, then I can call the second version foo(100,*this). Otherwise, I'll call the first version without passing *this.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
james
  • 1,107
  • 14
  • 29
  • What does a macro do? – aram Mar 28 '18 at 16:17
  • 7
    Macros are never "called" - they are expanded. –  Mar 28 '18 at 16:18
  • 2
    Macros do not exist in code – smac89 Mar 28 '18 at 16:19
  • Also note that `this` pointer only exists within either a constructor or a member function, whereas macros can be placed anywhere – smac89 Mar 28 '18 at 16:25
  • I don't understand why people are downvoting this question. Just because doing this is not a good idea to do this, doesn't mean it's a bad question. – einpoklum Mar 28 '18 at 16:25
  • 1
    @ein It is a bad question - it's not clear what the OP is asking, he doesn't show how his macro would be used, and he probably doesn't understand how macros are processed. –  Mar 28 '18 at 16:30
  • 2
    @einpoklum I was waffling over that. The question shows poor research into what macros are and how they work but is otherwise a reasonable question. I see this more as [an X-Y problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). More details on the actual goal and odds are good someone could suggest a work-around better tailored than your suggestion of a `constexpr` function. – user4581301 Mar 28 '18 at 16:33
  • 1
    @NeilButterworth: The title makes it clear to me. True, he wants to use it for something questionable/unreasonable/unadvisable/impossible, but he still told us what it basically is. Also, the fact that OP doesn't understand how macros work does not in itself make the question bad. – einpoklum Mar 28 '18 at 16:33
  • 1
    @user4581301: 1. It's more of an X-Y-Z question, but he's telling us what Y is and asking about Z. I'd say that's fair enough. 2. I don't believe all X-Y questions are bad; if Y does not lack obvious motivation, I'd say it's fine. A newbie may well come up with at least the title of this question. – einpoklum Mar 28 '18 at 16:36
  • 1
    X-Y's are what they are. When an asker is going down a rabbit hole, I think it is, in a way, up to those of us out here to prod a bit and see if we can redirect their line of inquiry. – user4581301 Mar 28 '18 at 16:41
  • 1
    @user4581301: That's fair, but prodding = commenting rather than downvoting. – einpoklum Mar 28 '18 at 17:29

3 Answers3

4

It isn't possible, strictly speaking, to have a macro recognize whether it's invoked within some class or not. You see, macros are expanded by a preprocessor - not by the C++ compiler proper; and the preprocessor has no clue about C++ - it just works on text files. When the actual compiler gets to recognizing the class, the macros are all gone already.

However, you can use some more macros to sort-of achieve this:

#define IN_CLASS_FOO 1
class foo {
    /* ... whatever ... */
}
#undef IN_CLASS_FOO
#define IN_CLASS_FOO 0

with this in place, you can modify your X macro to use IN_CLASS_FOO for controlling its behavior. Note that if you expand some code which refers to a this variable, it will have to be defined even if you're not within a class, so it would still not be possible to just use it.

I strongly discourage you from doing so, however - you would most likely be better served by avoiding macro use altogether. Try replacing the macro with a constexpr function.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • You should `#undef` before re-defining. – Aconcagua Mar 28 '18 at 16:25
  • See my comment in the question, but a macro will not be able to have access to `this` pointer, unless it is used inside a scope that has `this`. i.e. constructor, member functions, operators, etc – smac89 Mar 28 '18 at 16:26
  • @Aconcagua: Right. – einpoklum Mar 28 '18 at 16:27
  • @smac89: I didn't say anything about the `this` pointer in my answer. Also, textually, you can very well have a macro use `this`... – einpoklum Mar 28 '18 at 16:27
  • But that's the whole point of the question; "when in class, use `this`, else don't". If you really want to suggest using a macro to determine when inside a class scope, then in the context of this question, that `IN_CLASS_FOO` should be defined only in places where `this` is accessible – smac89 Mar 28 '18 at 16:29
  • @smac89: I wouldn't say it's the point of the question, it's the _motivation_ for the question. But see edit. – einpoklum Mar 28 '18 at 16:36
  • Big problems are imposed by *static* functions - there is no this, but we are still in class... I suppose this simply wasn't seen by OP when saying "within class", but it's exactly what makes @smac89 getting the score here... Minimally, the problem should be mentioned (not only here in comment). – Aconcagua Mar 28 '18 at 17:00
1

The keyword this is available within the body of any non-static member function. Once I saw a pretty old code in macroses like this:

__if_exists(this) \
  { \
  // Do something
  } \

Statement __if_exists checks in compile-time if the identifier is available in this scope.

But be careful, it is supported by MSVS only, and in general, it is not good to use such things in the code.

Vladislav
  • 394
  • 1
  • 14
0

Too little information in the question, so the following could be a match or it might not...

class C
{
    void foo(int a)
    {
        ::foo(a, *this);
    //  ^^ resolves to global scope
        bar::foo(a, *this);
    //  ^^ assuming foo resides in namespace "bar"
    }
};

So you now have a member function that will be selected whenever you call e. g. foo(77) within the class context, otherwise, the free foo overload will be selected. The macro gets pointless, just drop it.

If it is OK for you that the template parameter will be resolved to class C only, even if called from within sub classes, you could inherit from C for not having to repeat this code in every sub class. Otherwise, you'll get away with curiously recurring templates...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59