преобразование имени переменной в строку в C++

Я хотел бы вывести некоторые данные в файл. Например, предположим, что у меня есть два вектора двойников:

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

есть ли простой способ вывести это в файл, чтобы первая строка содержала заголовки "data1" и "data2", а затем фактическое содержимое. Функция, которая выходные данные будут передаваться различными различными массивами, поэтому hardcoding имя заголовка невозможно - в идеале я хотел бы преобразовать имя переменной в некоторую строку, а затем выведите эту строку далее следует содержимое векторного массива. Однако я не уверен, как преобразовать имя переменной "data1" в строку, или действительно, если это можно легко сделать (из чтения форумов я предполагаю, что это не может) Если это невозможно, альтернативой может быть использование ассоциативного контейнер, такой как map или, возможно, более простой контейнер "пара".

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

любые предложения будут приветствоваться!

8 ответов


вы можете использовать препроцессор "stringify"# делать то, что вы хотите:

#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

(жаль printf, Я не понял <iostream>. Но этого должно быть достаточно.)


попробуйте это:

#define GET_VARIABLE_NAME(Variable) (#Variable)

//в функции

int var=0;    
char* var_name= GET_VARIABLE_NAME(var);

вы можете использовать препроцессор, есть токен stringify, но он доступен только из источника, а не для функции (вы получите имя аргумента).


Я бы подумал, что очевидным ответом является то, чтобы функция, выполняющая вывод, принимала текст заголовка в качестве строкового параметра.


слегка адаптировано из ответа @sarnold, для C++:

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

пример программы, которая использует этот:

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

    return 0;
}

у меня была та же проблема. После небольшого эксперимента я создал следующие макросы, которые преобразуют имена переменных, полей, функций, методов и типов в строки.

#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)

код использует оператор запятой и преобразование void, чтобы заставить компилятор проверить переменную, функцию и т. д. действительно существовать. Хорошо, что он хорошо работает и с неинициализированными переменными. Я тестировал его как на VC, так и на GCC со всеми педантичными вариантами, которые я узнал без предупреждения сообщения.

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

int Variable=GetAndPrintValue(MACRO_VARIABLE_TO_STRING(Variable));

Я использую такой код, когда пишу синтаксические анализаторы, которые считывают данные из входного потока, и если анализируемая переменная выходит за рамки, она выдает исключение с именем переменной, которая не прошла мои проверки правильности.


для этого случая я сделал nameof () макрос. Он возвращает std:: string имя переменной, типа или члена. Он работает как nameof () в C#.

Например:

#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

Вау, это немного хитро, одна вещь, которую вы можете попытаться сделать, это сделать классы или структуры, которые имеют элемент, который является строкой "имя".