converting a variable name to a string in C++
Asked Answered
M

8

58

I'd like to output some data to a file. For example assume I have two vectors of doubles:

vector<double> data1(10);
vector<double> data2(10); 

is there an easy way to output this to a file so that the first row contains the headings 'data1' and 'data2' followed by the actual contents. The function which outputs the data will be passed various different arrays so hardcoding the name of the heading is not possible - ideally I'd like to convert the variable name to some string and then output that string followed by the contents of the vector array. However, I'm not sure how to convert the variable name 'data1' to a string, or indeed if it can easily be done (from reading the forums my guess is it can't) If this is not possible an alternative might be to use an associative container such as map or perhaps more simply a 'pair' container.

pair<vector<double>,string> data1(10,'data1');  

Any suggestions would be welcome!

Mesics answered 2/8, 2010 at 10:25 Comment(3)
I have to wonder what you are trying to achieve. If it is arbitrary amounts of data, naming each part of it won't do you any good, because it has to be done by hand anyway. Your second solution is probably the one you are looking for.Gearldinegearshift
Wow, this is a bit trickey, one thing you could try to do is make classes or structs, which have an element that is the string 'name'.Messner
related #202093Fuddle
M
83

You can use the preprocessor "stringify" # to do what you want:

#include <stdio.h>

#define PRINTER(name) printer(#name, (name))

void printer(char *name, int value) {
    printf("name: %s\tvalue: %d\n", name, value);
}

int main (int argc, char* argv[]) {
    int foo = 0;
    int bar = 1;

    PRINTER(foo);
    PRINTER(bar);

    return 0;
}


name: foo   value: 0
name: bar   value: 1

(Sorry for printf, I never got the hang of <iostream>. But this should be enough.)

Meghannmegiddo answered 2/8, 2010 at 10:40 Comment(2)
Nice. printf is fine in my opinion, just another option for ouput. They're all the same to me.Bridges
@cs1349459 in a small toy like this, yes, C stdio isn't much different from the C++ iostreams. However, in larger projects, quite often the C++ iostream synchronizing with C stdio takes enough time that it is disabled. Mixing stdio with iostreams in that case will probably cause surprising behavior. I still don't understand iostream well :) so head to en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio for more information.Meghannmegiddo
H
25

try this:

#define GET_VARIABLE_NAME(Variable) (#Variable)

//in functions

int var=0;    
char* var_name= GET_VARIABLE_NAME(var);
Hudibrastic answered 29/9, 2016 at 16:41 Comment(0)
R
8

I had the same problem. After a little bit of experimentation I created following macros that convert names of variables, fields, functions, methods and types to strings.

#define MACRO_VARIABLE_TO_STRING(Variable) (void(Variable),#Variable)

#define MACRO_FUNCTION_TO_STRING(Function) (void(&Function),#Function)

#define MACRO_METHOD_TO_STRING(ClassName,Method) (void(&ClassName::Method),#Method)

#define MACRO_TYPE_TO_STRING(Type) (void(sizeof(Type)),#Type)

The code uses comma operator and void conversion to force compiler to check if variable, function, etc. really exists. The nice thing is that it works well with uninitialized variables too. I tested it on both VC and GCC with all pedantic options I found out without any warning messages.

int GetAndPrintValue(const char* VariableName)
{
   std::cout << VariableName << std::endl;
   return 10;
}

int Variable=GetAndPrintValue(MACRO_VARIABLE_TO_STRING(Variable));

I use such code when I write parsers that reads data from input stream and if parsed variable is out of bounds it throws an exception with name of variable that failed my validity checks.

Rech answered 6/9, 2016 at 9:49 Comment(1)
An excellent solution in my viewClarissaclarisse
C
5

Slightly adapted from @sarnold's answer, for C++:

#define DEBUG(x) std::cerr << #x << " = " << x << std::endl;

An example program which uses this:

int main() {
    int foo = 1;
    DEBUG(foo);

    return 0;
}
Clarethaclaretta answered 6/4, 2015 at 16:18 Comment(2)
Hey, I use this in my competitive programming template. For a debugging aid it might be better to use std::cerr to distinguish it from stdout.Stereogram
Agreed. Updated.Clarethaclaretta
W
3

You can use the preprocessor, there's a stringify token, but it's only available from the source, not to a function (you'd get the argument name).

Wordage answered 2/8, 2010 at 10:30 Comment(0)
S
2

I had a similar quest. In Qt, I got tired of constantly writing the variable name as a string without autocomplete when writing to qDebug(). After a lot of trial and error with different macros and functions, I found that this macro works great:

#define PRINT(x) ", " << #x << ": " << x

Example usage:

int someVariable = 42;
double anotherVariable = 13.37;
qDebug().nospace() << "Some text" << PRINT(someVariable) << PRINT(anotherVariable);

Output:

Some text, someVariable: 42, anotherVariable: 13.37

I guess this (or something very similar) will work for std::cout as well.

A bit late to the party, but I hope this can help anyone out there!

Semipalatinsk answered 23/11, 2020 at 14:29 Comment(0)
F
1

I'd have thought the obvious answer is to make the function that performs the output take the heading text as a string parameter.

Foreshore answered 2/8, 2010 at 10:34 Comment(1)
Ideally I'd like to be able to call the function that does the output without a string parameter containing the names of the varialbes.Mesics
D
1

For this case I have made nameof() macro. It returns a std::string name of a variable, type or member. It works like nameof() in C#.

For Example:

#include "nameof.h"

std::vector<double> data1(10);
std::string name = nameof(data1); // "data1"

struct Foo1
{
    struct Foo2
    {
        Foo1* foo1;
    };

    Foo1* foo1;
    Foo2 foo2;
};

name = nameof(Foo1::foo1->foo2.foo1); // "foo1"

name = nameof(123); // std::logic_error exception
Dexterdexterity answered 5/2, 2018 at 10:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.