43

I want my exception messages to contain information about the exception location.

So I would like to have something like this:

#define LOCATION __FILE__ " : " __LINE__

throw std::exception(std::string("ABCD. ") + LOCATION);

That define is obviously incorrect. How can I achieve this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
NFRCR
  • 5,304
  • 6
  • 32
  • 37

1 Answers1

74

You need to expand that macro in two levels:

#define S1(x) #x
#define S2(x) S1(x)
#define LOCATION __FILE__ " : " S2(__LINE__)

Here is the reason:

You need expand __LINE__ in two levels, before passing it to #x.

First of all, using operator # in a function-like macro, it has to be followed by a macro parameter but __LINE__ is not a parameter, so compiler complains it's a stray operator.

On the other hand, __LINE__ itself is a macro and contains current line number, it should be expanded to the number before using it with #, otherwise, you will get string "__LINE__" instead of a number.

Macro S2(__LINE__) expands __LINE__ to a line number, then we pass the line number to #x.

masoud
  • 55,379
  • 16
  • 141
  • 208
  • 2
    What if I want to add __PRETTY_FUNCTION__ as a third one? Thanks in advance! – uss Mar 20 '15 at 12:16
  • 5
    Boost's [`BOOST_PP_STRINGIZE(__LINE__)`](http://www.boost.org/doc/libs/1_49_0/libs/preprocessor/doc/ref/stringize.html) does that, in case you don't want to create your own macros S1 and S2. – AndiDog Apr 10 '15 at 08:52
  • 1
    @sree: #define LOCATION std::string(__PRETTY_FUNCTION__) + " :: " + std::string(__FILE__) + ":" + std::string(S2(__LINE__)) – adiog May 02 '16 at 20:08
  • @adiog While to OP asked for a string for an exception, i.e. used in a function, you get an error with your proposal here: `char foo[] = LOCATION;` at file scope as well as in a function. – harper Oct 22 '19 at 08:41