Простое отражение C++ без макросов: печать имени переменной и ее значения

Есть ли в С++ немакро-способ печати имени переменной с ее значением. Вот способ макроса:

#define SHOW(a) std::cout << #a << ": " << (a) << std::endl

PS: я использую Linux и мне не нужно кроссплатформенное решение


person Alan Turing    schedule 27.07.2011    source источник
comment
зачем вам это без макроса? Вы хотите сделать это во время выполнения?   -  person balki    schedule 27.07.2011
comment
@balki: Какое это имеет значение?   -  person Jacob    schedule 28.07.2011
comment
@baiki, нет, не во время выполнения, но я хочу избежать использования макросов в этом случае (и вообще) из-за конфликтов имен и отсутствия перегрузочной функциональности.   -  person Alan Turing    schedule 28.07.2011


Ответы (4)


Вы можете использовать динамические символы, но тогда это будет работать только в разделяемых библиотеках или исполняемых файлах, скомпилированных с флагом -rdynamic. И он будет распознавать только глобальные переменные с динамической видимостью по умолчанию.

#include <dlfcn.h>
#include <iostream>

int NameMe = 42;

const char *GetName(const void *ptr)
{
    Dl_info info;
    if (dladdr(ptr, &info))
        return info.dli_sname;
    else
        return NULL;
}

    template<typename T>
void Dump(const T &t)
{
    const char *name = GetName(&t);
    if (name)
        std::cout << name;
    else
        std::cout << "<unknown>";
    std::cout << ": " << t << std::endl;
}
int main()
{
    int NoName = 33;
    Dump(NameMe);
    Dump(NoName);
    return 0;
}

$ g++ dump.cpp -ldl -rdynamic
$ ./a.out
NameMe: 42
<unknown>: 33
person rodrigo    schedule 27.07.2011

Нет, С++ не поддерживает отражение, и единственный способ сделать это (насколько мне известно) — макросы.

person Jacob    schedule 27.07.2011
comment
Между прочим, я хорошо знаю, что C++ изначально не поддерживает отражение, однако я подумал, что могут быть некоторые мощные решения, которые не являются кросс-платформенными, о которых я не знал. - person Alan Turing; 28.07.2011
comment
@Lex: я понимаю это; поэтому я специально упомянул, что это невозможно без макросов (ваше единственное ограничение). - person Jacob; 28.07.2011
comment
Отражение @AlanTuring на других языках, вероятно, на каком-то уровне зависит от макросов. Python сам по себе является макросом. Назовите его другим именем, но слой интерпретации или промежуточная компиляция предоставляет свойства, аналогичные макросам. - person Chris; 29.04.2020

Ни за что.

Без макроса вы должны сделать это:

std::cout <<"a : " << a << std::endl; 

Другого пути нет.

person Nawaz    schedule 27.07.2011

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

struct Reflector
{
    virtual void Show() = 0;
};
template<class a, char name[]>
struct ReflectorImpl : public Reflector
{
    virtual void Show()
    {
        std::cout << name << ": " << *this << std::endl;
    }
};

class MyClass: public ReflectorImpl<MyClass, "MyClass">
{
};
person Mark Ransom    schedule 27.07.2011
comment
Я не знаю, будет ли cout *this работать без определения operator<< в классе. Я бы реализовал Show() в базовом классе и заставил (через чистый абстрактный метод в базовом классе) подклассы определить operator<< или какой-то метод ToString. - person qid; 28.07.2011