Chris Smith
Chris Smith

Reputation: 3012

Function not implemented macro?

I'm trying to create a macro so I can specify that a function is not implemented yet (and will crash the program when invoked). Here's what I came up with:

#define NIMPL crash(__PRETTY_FUNCTION__ " not implemented yet")

And you'd use it like so:

void myFunction() {
    NIMPL;
}

However, this usage causes this error:

../feta/include/feta.h:19:41: error: expected ‘)’ before string constant
 #define NIMPL crash(__PRETTY_FUNCTION__ " not implemented yet")
                                         ^

crash() is a function that accepts one string as a parameter, prints out the message, and calls exit(1).

I can confirm that __PRETTY_FUNCTION__ alone, without the concatenation works fine. Also, concatenating two strings without __PRETTY_FUNCTION__ works fine: "<stuff>""<other stuff>". But doing both at the same time does not work.

I've tried using the stringizing operator, but it did not work (if it even exists in GCC).

Upvotes: 2

Views: 3147

Answers (2)

jxh
jxh

Reputation: 70442

In C (as the question was originally tagged), __PRETTY_FUNCTION__ is another name for __func__, which is not a string literal. In C++, it is decorated with the function signature, but it is still not a string literal.

From the documentation (especially note the last sentence):

The identifier __func__ is implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration

static const char __func__[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing function. This name is the unadorned name of the function. As an extension, at file (or, in C++, namespace scope), __func__ evaluates to the empty string.
...
In C, __PRETTY_FUNCTION__ is yet another name for __func__, except that at file (or, in C++, namespace scope), it evaluates to the string "top level". In addition, in C++, __PRETTY_FUNCTION__ contains the signature of the function as well as its bare name.
...
These identifiers are variables, not preprocessor macros, and may not be used to initialize char arrays or be concatenated with string literals.

Since you are using C++, you may consider defining crash as a variadic template function rather than a macro, to provide some more flexibility.

void crash_t (std::ostringstream &oss)
{
    oss << std::endl;
    write(2, &oss.str()[0], oss.str().size());
    exit(1);
}

template <typename A, typename... REST>
void crash_t (std::ostringstream &oss, A arg, REST... rest)
{
    oss << arg;
    crash_t(oss, rest...);
}

template <typename... ARGS>
void crash (ARGS... args)
{
    std::ostringstream oss;
    crash_t(oss, args...);
}

Upvotes: 2

Keith Thompson
Keith Thompson

Reputation: 263387

Standard C and C++ provide the "magic identifier" __func__, which acts as if it were the name of a static char array containing the name of the current function. (Actually the value is implementation-defined in C++.)

gcc, as an extension, provides __PRETTY_FUNCTION__, which is identical to __func__ for C, and provides some additional information for C++.

That doesn't solve the problem you're asking about, which is that string literal concatenation applies only to string literals.

You say your crash() function takes a single string as an argument.

I suggest either modifying crash() so it takes two arguments, or writing a new wrapper function that takes two arguments. You can then use:

#define NIMPL crash(__PRETTY_FUNCTION__, " not implemented yet")

(Since you're using C++ you can overload it with the same name.) Concatenating the two strings is left as an exercise.

You could also add a second string argument to your existing crash() function and give it a default value of "" to avoid breaking existing calls.

Upvotes: 3

Related Questions