0

My program(C++) is defining a macro for throw statements. It is something like:

#define FOO_THROW(some-exception-type, some-error-message)  \
    do                                                      \
        {                                                   \
            [&]() __attribute__((cold, noinline))           \
            {                                               \  
                using exception_type = some-exception-type; \     
                std::ostringstream ss;                      \
                ss << some-error-message << "";             \               
                throw exception_type(ss.str());             \
            }                                               \
            ();                                             \
        }                                                   \
    while (0);

Then, it is getting called in the program, something like:

FOO_THROW(std::runtime_error, "error specfic message here")

I can see that we use do...while(0) structure with the macro, what I want to understand is the use of lambda and __attribute__ here, can someone explain that in simple words?

Basically, my focus is what is the need of lambda function here, when it can be done without it, is there can be any specific advantage of it here?

I am a beginner in C++, so any hint in the right direction will do as well!

DonBaka
  • 325
  • 2
  • 14
  • My apologies, but where did you take this definition from? Because the way I see it, this shouldn't be working at all. Macros need to be 'one liners', as such potential newlines need to be escaped. The do while is 'without effect' and it would be the same, if it wasn't there at all. (Gets executed exactly once.) – Refugnic Eternium Oct 13 '21 at 08:49
  • @RefugnicEternium it is actually escaped, I forgot to add it, updating now... – DonBaka Oct 13 '21 at 08:52
  • Whereas I still don't know what the do/while is for, the lambda takes the role of an anonymous function. The attributes are described under 'https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html'. Basically it's a 'raise exception of type 'x' with the error message 'y'. Though, to be honest, I don't see why you can't just write `throw std::runtime_error("error specific message here");` in the first place. – Refugnic Eternium Oct 13 '21 at 08:54
  • @RefugnicEternium the macro is doing an extra work of string-stream, which is a bit lengthy with `throw std::runtime_error("THIS-NEEDS-A-STRING-STREAM");` – DonBaka Oct 13 '21 at 08:57
  • See e.g. https://stackoverflow.com/questions/154136/why-use-apparently-meaningless-do-while-and-if-else-statements-in-macros for the `do ... while(0)`. – Holt Oct 13 '21 at 08:57
  • In fact, it does not pass a string stream to the constructor of runtime_error, but much rather an `std::string`. Furthermore, `std::string` has a constructor for taking a const char *, making the detour around stringstream necessary. At least that's my opinion. – Refugnic Eternium Oct 13 '21 at 09:00
  • Thanks for the heads up about the do/while, @Holt. I certainly did not know that. – Refugnic Eternium Oct 13 '21 at 09:02
  • @RefugnicEternium actually the macro is implemented in two smaller macros and taking string-stream in between, something like `FOO_THROW << "TAKING-STRING-STREAM" << FOO_END` – DonBaka Oct 13 '21 at 09:04
  • @RefugnicEternium it does allow passing anything streamable, e.g. `FOO_THROW(std::runtime_error, "some message" << var << "more message")` – Caleth Oct 13 '21 at 10:01

1 Answers1

1

do...while(0) allows the macro to by called with semicolon at the end, i.e. macro(x,y,z); (note the semicolon at the end), that's an old trick back from C, you can look it up separately.

As for the rest... it defines a lambda (immediate function object) capturing everything by reference (not sure why) that throws exception of a given type with a given message and calls it immediately, effectively throwing an exception.

The attributes signify the lambda is unlikely to be called (cold) and prevent from inlining (noinline), see: https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html

alagner
  • 3,448
  • 1
  • 13
  • 25