2014-09-17 3 views
3

Я хотел бы напечатать имя типа для целей отладки, поэтому я создал функцию, которая делает трюк (на самом деле, я заимствовал ее из другого ответа SO, который Я не могу нашел сейчас), функция выглядит следующим образом:Шаблон, который печатает имя данного типа

template <typename T> std::string TypeName(T) 
{ 
    auto name = typeid(T).name(); 
    int status = 0; 

    std::unique_ptr<char, void(*)(void*)> res { 
     abi::__cxa_demangle(name, NULL, NULL, &status), 
     std::free 
    }; 

    return ((status == 0) ? res.get() : name); 
} 

Live Demo

Он отлично работает:

int i = 0; 
float f = 0.f; 

std::cout << TypeName(i) << '\n'; // int 
std::cout << TypeName(f) << '\n'; // float, so far so good 

std::cout << TypeName(&i) << '\n'; // int * 
std::cout << TypeName(&f) << '\n'; // float *, as expected 

Но ему не хватает емкости борьбы с top-level cv-cualifiers и ссылок:

const int ci = 1; 
const float cf = 1.f; 

std::cout << TypeName(ci) << '\n'; // int! (instead of const int) 
std::cout << TypeName(cf) << '\n'; // float! (instead of const float) 

int &ri = i; 
float &rf = f; 

std::cout << TypeName(ri) << '\n'; // int! (instead of int &) 
std::cout << TypeName(rf) << '\n'; // float! (instead of float &) 

Ну, я не могу сказать, что это является неожиданным, так как функция TypeName шаблон функции и тип T следует тип шаблона вычет но эта проблема делает все это почти бесполезным.

Итак, мой вопрос: есть ли что-нибудь, что можно сделать для создания функции шаблона (который может получить любой тип в качестве ввода), чтобы получить имя типа без потери верхних уровней cv-cualifiers и ссылок?

Заранее спасибо.

+1

Вопрос о том, чтобы найти рабочий стол для этой проблемы, нет проблемы с 'typeid', IMHO не является дубликатом. –

ответ

1

только C++, языковая конструкция, которая может отличить именующую, который представляет собой идентификатор выражения и именующий, который является ссылка decltype. Вот пример того, как использовать его, в том числе (аb) использование макроса, чтобы сохранить тот же шаблон вызова у вас уже есть:

template <typename T> std::string TypeName() { 
    auto name = typeid(T()).name(); // function type, not a constructor call! 
    int status = 0; 

    std::unique_ptr<char, void(*)(void*)> res { 
     abi::__cxa_demangle(name, NULL, NULL, &status), 
     std::free 
    }; 

    std::string ret((status == 0) ? res.get() : name); 
    if (ret.substr(ret.size() - 3) == "()") ret.resize(ret.size() - 3); 
    return ret; 
} 
#define TypeName(e) TypeName<decltype(e)>() 

Поскольку abi::__cxa_demangle игнорирует резюме и контрольные отборочные верхнего уровня, мы строим тип функции а затем разделите скользящие скобки.

Это дает int const, int&, по мере необходимости.

Смежные вопросы