-4

I'm trying to create a C++ macro with a variable number of arguments (0 to 1) which will act as a wrapper to a function call in order to supply the this pointer of a calling object as a default argument value.

So that the user could make the calls:

    CALL(pointer) // An argument is supplied, pass it to the call
    CALL()        // No argument supplied, pass the this pointer value instead
  • 3
    1. What is the actual question? 2. What have you tried doing so far? – UnholySheep Nov 02 '16 at 15:54
  • C++ macros don't have a lot of capability, I'd suggest finding another way to do what you want. – Mark Ransom Nov 02 '16 at 15:54
  • 1
    @MarkRansom Boost.PP disagrees with you :) – Quentin Nov 02 '16 at 15:56
  • duplicate of http://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros – UKMonkey Nov 02 '16 at 15:57
  • @UnholySheep The question is really long, so I came up with this abstract but very neat question. The reason I am emphasizing the 'this' pointer is because the macro can't be replaced by a template or factory function. Here is a thread with more details http://stackoverflow.com/questions/40362672/a-macro-to-choose-the-object-instantiation-based-on-the-amount-of-the-arguments – Roman Zacharia Nov 02 '16 at 16:16
  • @MarkRansom I've tried a lot and solving this puzzle looks the most promising. – Roman Zacharia Nov 02 '16 at 16:16
  • @UKMonkey No it is not duplicate. Please read carefully: I am asking about a macro with a variable number of arguments not a macro argument default value. – Roman Zacharia Nov 02 '16 at 16:16
  • @Quentin let me provide some advice then - only use macros if they make your code clearer. That's unlikely to be the case here, the macro itself will be nearly unintelligible. – Mark Ransom Nov 02 '16 at 16:17
  • @user3348108 what you're asking for is an "optional number of arguments" - as you know, the definition of an optional argument is one that has a default value assigned to a value that marks it as invalid. – UKMonkey Nov 02 '16 at 16:19
  • I agree with the others. The macro doesn't seem worth saving the 4-6 characters for `this, `, which would make things 10x clearer to future developers. It also reduces the problem to just a few function overloads instead of a huge, difficult-to-understand set of macros. – Dark Falcon Nov 02 '16 at 16:47
  • @DarkFalcon the automatic detection of a cv-qualifier reduces the chance of a deadlock a lot. – Roman Zacharia Nov 02 '16 at 16:52
  • You can auto-detect the cv-qualifier with function overloads or with templates. – Dark Falcon Nov 02 '16 at 16:55
  • As far as I can tell, you _never actually asked a question_. Please [edit] your question to contain one -- a one-or-two-sentence summary of what you're trying to get out of this site, phrased so that ending it with `?` is grammatically correct. (P.S. Neat project! Best of luck.) – Nic Nov 02 '16 at 17:02
  • @DarkFalcon The produced object cannot be copied, and the move constructor cannot be added, so overloads or templates can't be used. – Roman Zacharia Nov 02 '16 at 17:10
  • @QPaysTaxes sarcasm? I added a question mark, but I'm sure the question was clear anyway. – Roman Zacharia Nov 02 '16 at 17:15
  • @user3348108 Look at the question before. It used to be "Here's what I'm trying to do," with no statement of why you're not able to. Now, it's a grammatically incorrect "How can I do this", which makes it clear what you're actually asking. – Nic Nov 02 '16 at 17:16
  • And why can you not overload the constructor? If the answer is because it isn't your class, then wrap it in your class. And don't try to micro-optimize that until you have tried it and proved that that is suboptimal and not just optimized out by your compiler. – Dark Falcon Nov 02 '16 at 17:17
  • @DarkFalcon as can be seen from the code, this is a synchronization class which is forbidden to be copied. Even if I wrap it I would still have to copy the object of the base class type which is forbidden. – Roman Zacharia Nov 02 '16 at 17:24
  • ......... This does *not* require copying. Why would you think it requires copying? I didn't say don't use any macro, I just said don't use a complicated macro. So your macro looks like `#define ENC_LOCK(...) MyLocker thelock(__VA_ARGS__);`. No copies. – Dark Falcon Nov 02 '16 at 17:28
  • @QPaysTaxes sorry for the grammar, I'm not a native speaker but trying hard. That is great that the question became clearer so now you can understand that. I am very upset and stressed that there is so much flood and downvoting and unrelated solutions because someone didn't read all the question details and no one is trying to help me fix the damn macro. – Roman Zacharia Nov 02 '16 at 17:32
  • @DarkFalcon I'm still convinced the overloads won't do the job. The default value for the argument would be the "this" pointer of a calling object. Your solution implies (I suppose) passing "this" to all overloads. But the object might be instantiated (with an argument which should replace "this") from a function where "this" is not defined. – Roman Zacharia Nov 02 '16 at 17:39
  • I'm saying you *manually specify* this. Then the need for a complicated macro goes away. See my first comment. https://godbolt.org/g/ycgPnB – Dark Falcon Nov 02 '16 at 17:43
  • @DarkFalcon Please read the initial question on the very first line. It asks about a macro with a zero to one arguments. Manually specifying makes no sense in the context of this question. – Roman Zacharia Nov 02 '16 at 17:49
  • 1
    I am fully aware of what you are asking. I'm saying you are doing it wrong. Read my first comment again. Stop being one of those people so fixated on one idea that they refuse to listen to any other idea. The down votes are intended to be a clue that you are doing something wrong here. I and most of the other commenters are indicating that the goal in the question is either unclear or just plain a bad idea. I gave my reasons why in the very first comment and have since provided a close alternative. I understand this doesn't answer the direct question, but it is giving a recommended alternative – Dark Falcon Nov 02 '16 at 17:55
  • @DarkFalcon thank you for your answers. What am I trying to say is that your solution is already implemented. That is what I have now in my code. I am astonished that getting rid of a single argument is so challenging and I like solving hard riddles. – Roman Zacharia Nov 02 '16 at 18:01
  • Then on future questions, it might be helpful to provide that up front. Otherwise everyone will think you're trying to engineer something from scratch with no idea what you're doing. Hence a lot of people wasting time telling you you're doing it wrong. Some might still take time to tell you your doing it wrong, but I bet you'd get a lot less arguments and downvotes. Do note that many questions on this site do come from people who have no idea how to architect a system and thus choose the most difficult way possible. Your question sounds like one of them. – Dark Falcon Nov 02 '16 at 18:10
  • (I do still think you're doing it wrong though. I still think you should always require the user to specify the locked object for clarity's sake.) – Dark Falcon Nov 02 '16 at 18:14
  • @user3348108, at the start of your question, you claim that you want to accept zero or one arguments. Then at the end you say you want to be able to pass zero, one, or *two* arguments to `ENC_LOCK`. Which is it? This is the kind of reason that causes great confusion here – Aaron McDaid Nov 02 '16 at 20:58
  • @AaronMcDaid Initially I simplified the case, does it really matter? – Roman Zacharia Nov 02 '16 at 21:20
  • I've just done a major reedit of this question, trying to make it more readable. It's still a mess, but better than it was – Aaron McDaid Nov 02 '16 at 21:25
  • The initial question was very short and clear. The mess appeared when I started answering all these questions which didn't change anything – Roman Zacharia Nov 02 '16 at 21:37

1 Answers1

0

You could use boost to write a macro that allows you to count how many parameters there are. However this only works if you have at least one parameter. When you have zero parameter boost thinks you have one. So this is not exactly an answer to your question (unless you can live with passing at least one parameter). I nonetheless post it as an answer because it might be helpful to people with similar situations, and the other "duplicate" issue's accepted answer does not provide this solution.

#include <iostream>
#include <boost/preprocessor/tuple/elem.hpp>

#define CALL(...)                                    \
  {                                                  \
    auto num = BOOST_PP_VARIADIC_SIZE(__VA_ARGS__);  \
    std::cout << "called with " << num << " args." << std::endl; \
  }

int main() {
  CALL(1, 2);
  CALL(1);
}
Donghui Zhang
  • 1,133
  • 6
  • 8