6

Возможно ли вывести тип переменной в стандартном C++?

1

Описание проблемы:

Я пытаюсь вывести тип переменной в C++, но, вместо ожидаемого результата, не могу добиться нужного вывода. Например, у меня есть следующий код:

int a = 12;
cout << typeof(a) << endl;

Я ожидаю, что результат будет:

int

Однако компилятор выдает ошибку, так как typeof не является допустимым оператором в стандартном C++. Как я могу получить тип переменной a во время выполнения программы?

5 ответ(ов)

2

Попробуйте:

#include <typeinfo>

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

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

1

Очень некрасиво, но рабочий вариант, если вам нужны только данные на этапе компиляции (например, для отладки):

auto testVar = std::make_tuple(1, 1.0, "abc");
decltype(testVar)::foo = 1;

Возвращает:

Компиляция завершена с ошибками:
source.cpp: В функции 'int main()':
source.cpp:5:19: ошибка: 'foo' не является членом 'std::tuple<int, double, const char*>'
0

Не забудьте подключить <typeinfo>

Я полагаю, вы говорите о определении типа во время выполнения (runtime type identification). Вы можете добиться этого следующим образом:

#include <iostream>
#include <typeinfo>

using namespace std;

int main() {
  int i;
  cout << typeid(i).name();
  return 0;
}

В этом примере мы используем typeid для получения информации о типе переменной i. Не забудьте подключить заголовочный файл <typeinfo> для правильной работы этой функции.

0

Обратите внимание, что имена, сгенерированные с помощью механизма RTTI в C++, не являются переносимыми. Например, для класса

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

будут получены следующие имена:

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

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

0

Как упоминалось, typeid().name() может возвращать "замангленный" (mangled) имя. В GCC (и некоторых других компиляторах) вы можете обойти это с помощью следующего кода:

#include <cxxabi.h>
#include <iostream>
#include <typeinfo>
#include <cstdlib>

namespace some_namespace { namespace another_namespace {

  class my_class { };

} }

int main() {
  typedef some_namespace::another_namespace::my_class my_type;
  // замангленное имя
  std::cout << typeid(my_type).name() << std::endl;

  // развязанное имя
  int status = 0;
  char* demangled = abi::__cxa_demangle(typeid(my_type).name(), 0, 0, &status);

  switch (status) {
    case -1: {
      // не удалось выделить память
      std::cout << "Не удалось выделить память" << std::endl;
      return -1;
    } break;
    case -2: {
      // некорректное имя по правилам манглинга C++ ABI
      std::cout << "Некорректное имя" << std::endl;
      return -1;
    } break;
    case -3: {
      // некорректный аргумент
      std::cout << "Некорректный аргумент для demangle()" << std::endl;
      return -1;
    } break;
 }
 std::cout << demangled << std::endl;

 free(demangled);

 return 0;
}

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь