Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A standard way for getting variable name at compile time

Is there some way in C++11 or higher to achieve a similar behavior to:

int some_int;
std::string x=variable_name<some_int>::value; //Theoretical code 
std::cout << x;

Result should be:

some_int

If not, is there a compiler specific way to do it? I am targeting MSVS.

like image 826
Humam Helfawi Avatar asked Aug 01 '16 10:08

Humam Helfawi


People also ask

What is known at compile time?

In computer science, compile time (or compile-time) describes the time window during which a computer program is compiled. The term is used as an adjective to describe concepts related to the context of program compilation, as opposed to concepts related to the context of program execution (runtime).

Can you print a variable name in C?

How to print and store a variable name in string variable? In C, there's a # directive, also called 'Stringizing Operator', which does this magic. Basically # directive converts its argument in a string. We can also store variable name in a string using sprintf() in C.

How are variable names stored?

Variable names are stored in the dictionary of the data file. Observe the following rules when establishing variable names or referring to variables by their names on commands: Each variable name must be unique; duplication is not allowed.

What is variable name in C?

Variable names in C are made up of letters (upper and lower case) and digits. The underscore character ("_") is also permitted. Names must not begin with a digit. Unlike some languages (such as Perl and some BASIC dialects), C does not use any special prefix characters on variable names.


1 Answers

You ask:

Is there some way in C++11 or higher to achieve a similar behavior to:

int some_int;
std::string x=type_name<some_int>::value; //Theoretical code 
std::cout << x;

Result should be:

some_int

Yes, you can just use the preprocessor's stringizing operator #:

#include <iostream>

#define NAME_OF( v ) #v

using namespace std;
auto main() -> int
{
    int some_int;
     //std::string x=type_name<some_int>::value; //Theoretical code 
    auto x = NAME_OF( some_int );
    (void) some_int;
    cout << x << endl;
}

If you're asking for something different, then please post a new question since this one has now been answered (amending the question would invalidate this answer).


As an example real world usage, here's macro to pass a variable and its name to a test function:

#define TEST( v ) test( v, #v )

If you want a compile time check that the name in question is a variable or type name, then you can simply apply sizeof, e.g. in a comma expression:

#define NAME_OF( v ) (sizeof(v), #v)

The difference between having sizeof or not, is whether this is guaranteed to be done purely at compile time, versus possibly generating code to also do something at run time.

To avoid a possible warning you can add a pseudo-cast to void:

#define NAME_OF( v ) ((void) sizeof(v), #v)

And to make this work also for a function name you can add a typeid:

#define NAME_OF( name ) ((void) sizeof(typeid(name)), #name)

Complete example:

#include <typeinfo>

#define NAME_OF( name ) ((void) sizeof(typeid(name)), #name)

void foo() {}

#include <iostream>
using namespace std;
auto main() -> int
{
    int some_int;
    (void) some_int;
     //std::string x=type_name<some_int>::value; //Theoretical code 
    auto v = NAME_OF( some_int );
    auto t = NAME_OF( int );
    auto f = NAME_OF( foo );
    #ifdef TEST_CHECKING
        (void) NAME_OF( not_defined );
    #endif
    cout << v << ' ' << t << ' ' << f << endl;
}

The checking is not 100% perfect, though, because it's still possible to pass a function invocation to the NAME_OF macro.

like image 109
Cheers and hth. - Alf Avatar answered Sep 27 '22 21:09

Cheers and hth. - Alf