Действительно ли возможно распечатать тип переменной в стандартном C++?

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

352
задан ThePCWizard 14 September 2015 в 02:57
поделиться

7 ответов

Другие ответы, включающие RTTI (идентификатор типа), вероятно, что Вы хотите, пока:

  • можно предоставить память наверху (который может быть значительным с некоторыми компиляторами)
  • имена классов возвраты компилятора полезны

, альтернатива, (подобный ответу Greg Hewgill), должна создать таблицу времени компиляции черт.

template <typename T> struct type_as_string;

// declare your Wibble type (probably with definition of Wibble)
template <>
struct type_as_string<Wibble>
{
    static const char* const value = "Wibble";
};

знать, что при обертывании объявлений в макрос Вы испытаете затруднения при объявлении названий шаблонных типов, берущих больше чем один параметр (например, станд.:: карта), из-за запятой.

Для доступа к названию типа переменной все, в чем Вы нуждаетесь,

template <typename T>
const char* get_type_as_string(const T&)
{
    return type_as_string<T>::value;
}
5
ответ дан James Hopkin 23 November 2019 в 00:24
поделиться

Вы могли использовать класс черт для этого. Что-то как:

#include <iostream>
using namespace std;

template <typename T> class type_name {
public:
    static const char *name;
};

#define DECLARE_TYPE_NAME(x) template<> const char *type_name<x>::name = #x;
#define GET_TYPE_NAME(x) (type_name<typeof(x)>::name)

DECLARE_TYPE_NAME(int);

int main()
{
    int a = 12;
    cout << GET_TYPE_NAME(a) << endl;
}

Эти DECLARE_TYPE_NAME определяют, существует для создания жизни легче в объявлении этого класса черт для всех типов, в которых Вы ожидаете нуждаться.

Это могло бы быть более полезно, чем решения, включающие typeid, потому что Вы добираетесь для управления выводом. Например, использование typeid для long long на моем компиляторе дает "x".

10
ответ дан Greg Hewgill 23 November 2019 в 00:24
поделиться

Можно использовать шаблоны.

template <typename T> const char* typeof(T&) { return "unknown"; }    // default
template<> const char* typeof(int&) { return "int"; }
template<> const char* typeof(float&) { return "float"; }

В примере выше, когда тип не будет подобран, он распечатает "неизвестный".

18
ответ дан Nick 23 November 2019 в 00:24
поделиться

Обратите внимание, что имена, сгенерированные функцией RTTI C++, не портативны. Например, класс

MyNamespace::CMyContainer<int, test_MyNamespace::CMyObject>

будет иметь следующие имена:

// MSVC 2003:
class MyNamespace::CMyContainer[int,class test_MyNamespace::CMyObject]
// G++ 4.2:
N8MyNamespace8CMyContainerIiN13test_MyNamespace9CMyObjectEEE

, Таким образом, Вы не можете использовать эту информацию для сериализации. Но тем не менее, идентификатор типа (a) .name () свойство может все еще использоваться в целях журнала/отладки

22
ответ дан paercebal 23 November 2019 в 00:24
поделиться

Не забывайте включать <typeinfo>

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

#include <iostream>
#include <typeinfo>

using namespace std;

int main() {
  int i;
  cout << typeid(i).name();
  return 0;
}
53
ответ дан BartoszKP 23 November 2019 в 00:24
поделиться

Попытка:

#include <typeinfo>

// …
std::cout << typeid(a).name() << '\n';

Вам, возможно, придется активировать RTTI в Ваших параметрах компилятора для этого для работы. Кроме того, вывод этого зависит от компилятора. Это могло бы быть необработанное имя типа или символ искажения имени или что-либо промежуточное.

224
ответ дан Konrad Rudolph 23 November 2019 в 00:24
поделиться

Howard Hinnant используемые магические числа для извлечения имени типа. еє · жЎ “з‘‹ предложенный строковый префикс и суффикс. Но префикс/суффикс продолжает изменяться. С вЂњprobe_type” type_name автоматически вычисляет префикс и суффиксные размеры для “probe_type” для извлечения имени типа:

#include <iostream>
#include <string_view>

using namespace std;

class probe_type;

template <typename T>
constexpr string_view type_name() {
  string_view probe_type_name("class probe_type");
  const string_view class_specifier("class");

  string_view name;
#ifdef __clang__
  name = __PRETTY_FUNCTION__;
  probe_type_name.remove_prefix(class_specifier.length());
#elif defined(__GNUC__)
  name = __PRETTY_FUNCTION__;
  probe_type_name.remove_prefix(class_specifier.length());
#elif defined(_MSC_VER)
  name = __FUNCSIG__;
#endif

  if (name.find(probe_type_name) != string_view::npos)
    return name;

  const string_view probe_type_raw_name = type_name<probe_type>();

  const size_t prefix_size = probe_type_raw_name.find(probe_type_name);

  name.remove_prefix(prefix_size);
  name.remove_suffix(probe_type_raw_name.length() - prefix_size - probe_type_name.length());

  return name;
}

class test;

int main() {
  cout << type_name<test>() << endl;

  cout << type_name<const int*&>() << endl;
  cout << type_name<unsigned int>() << endl;

  const int ic = 42;
  const int* pic = &ic;
  const int*& rpic = pic;
  cout << type_name<decltype(ic)>() << endl;
  cout << type_name<decltype(pic)>() << endl;
  cout << type_name<decltype(rpic)>() << endl;

  cout << type_name<probe_type>() << endl;
}

Вывод

gcc 10.0.0 20 190 919 Wandbox:

 test
 const int *&
 unsigned int
 const int
 const int *
 const int *&
 constexpr std::string_view type_name() [with T = probe_type; std::string_view = std::basic_string_view<char>]

лязг 10.0.0 Wandbox:

 test
 const int *&
 unsigned int
 const int
 const int *
 const int *&
 std::__1::string_view type_name() [T = probe_type]

версия 16.3.3 VS 2019:

class test
const int*&
unsigned int
const int
const int*
const int*&
class std::basic_string_view<char,struct std::char_traits<char> > __cdecl type_name<class probe_type>(void)
2
ответ дан 23 November 2019 в 00:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: