Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you convert __func__ to a wchar_t[] at compile time?

Tags:

c++

visual-c++

So I have this snippet of code

wchar_t funcName[] = __FUNCTIONW__;

but the problem with __FUNCTIONW__ is it has class info in the name when all I want is the function name. Now__FUNCTIONW__ just calls _CRT_WIDE(__FUNCTION__) which made me think I could call _CRT_WIDE(__func__) but that gives an error "identifier L__func__ is undefined"

__func__ is an implicitly declared identifier that expands to a character array variable containing the function name when it is used inside of a function. It was added to C in C99. From C99 §6.4.2.2/1:

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.

I take this to mean __func_ is not a macro and it has nothing to do with preprocessing?

Is there another way I can get a wchar_t array at compile time?

like image 771
noztol Avatar asked Jul 19 '16 19:07

noztol


1 Answers

As you cited the C standard already (actually, it's the bad one, you need C++ standard, but there you find the same...):

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

You have now the same problem as if you wanted to convert any arbitrary other array at compile time, e. g.:

char buffer[16];
// convert to wchar_t[16]?

int array[4];
// convert to double[4]?

Type of array is int[4]. That is fix. It occupies 4*sizeof(int) bytes in memory, typically 16 bytes for most of nowaday's machines, which you can't magically change to 4*sizeof(double) bytes, typically 32 bytes (would be a nice trick to get a memory upgrade for free...).

There is no way to change char const __func__[] to a wchar_t[] at compile time, sorry. On the other hand, you should be able to use the ordinary char const array __func__ in many places you would use the wchar_t array (the array, not the wide string literal!):

std::wofstream ws; ws << __func__;
wchar_t buffer[64]; swprintf(buffer, sizeof(buffer), L"%s\n", __func__);

Problem will be with functions accepting e. g. wchar_t* while not having a char* overload. Then you won't get around converting the string at runtime (see mbstowcs).

If it helps, this might be an idea how to conveniently do it only once per function:

template <size_t N>
struct F
{
    wchar_t name[N];
    F(char const* func)
    {
        mbstowcs(name, func, N);
    }
};
#define F_INIT static F<sizeof(__func__)> func(__func__)
#define FUNC func.name

void foo()
{
    F_INIT;
    std::wcout << FUNC;
}

int main(int argc, char* argv[])
{
    F_INIT;
    std::wcout << FUNC;
    return 0;
}

Give them (template + macros) whatever name appears most appropriate to you...

like image 171
Aconcagua Avatar answered Sep 18 '22 07:09

Aconcagua