Получение типа авто в С++ 11 без выполнения программы
У меня есть код С++ 11 с использованием типа auto
, который я должен преобразовать в С++ 98. Как мне перейти на преобразование кода, заменяя фактический тип для всех экземпляров auto
?
Ответы
Ответ 1
Это будет PITA, но вы можете объявить неполный шаблон структуры, принимающий один параметр типа.
Учитывая переменную x
, которую вы хотите знать о типе, вы можете использовать struct с decltype(x)
, и это приведет к ошибке компилятора, которая покажет вам выведенный тип.
Например:
template<class Type> struct S;
int main() {
auto x = ...;
S<decltype(x)>();
}
Live demo
который выдает сообщение об ошибке в форме:
error: implicit instantiation of undefined template 'S<X>' (clang++)
error: invalid use of incomplete type 'struct S<X>' (g++)
когда x
является выведенным типом. В этом конкретном случае тип int
.
Общая информация: Это было рекомендовано Скоттом Мейером в одном из последних видеороликов NDC 2014 (я не помню, какой именно).
Ответ 2
Как auto
известно во время компиляции, вам необходимо взаимодействовать с компилятором.
Одним из вариантов может быть компилятор Clang библиотека LibTooling который предоставляет инфраструктуру, на которой вы можете использовать инструменты статического анализа.
Например, посмотрите на код примера рефакторинга, который удаляет лишние вызовы .c_str()
из кода. Я думаю, вы могли бы написать аналогичный инструмент, который преобразует auto
в выводный тип.
Ответ 3
Вы можете попробовать использовать макрос BOOST_AUTO
в Boost typeof library.
auto x = 5 + 7;
становится
BOOST_AUTO(x,5+7);
Ответ 4
Вы можете использовать typeid и std:: type_info:: name();
#include <iostream>
#include <typeinfo>
#include <complex>
int
main()
{
using namespace std::literals::complex_literals;
auto x = 3.1415F;
std::cout << typeid(x).name() << '\n';
auto z = 1.0 + 1.0i;
std::cout << typeid(z).name() << '\n';
}
$ /home/ed/bin_concepts/bin/g++ -std=c++14 typeid.cpp
$ ./a.out
f
St7complexIdE
Имена не красивы, но вы можете хотя бы перевести их.
Эти имена получены из g++. Имя зависит от компилятора.
Существует некоторое движение, чтобы стандартизировать pretty_name().
Здесь является нестандартным способом развязывания имен.
Ответ 5
Альтернативный подход заключается в использовании шаблонов функций и вычета типов. Он может работать не во всех примерах, но может помочь в некоторых случаях:
int foo ()
{
auto x = bar();
// do something with 'x'
}
Измените это на:
template <typename T> int foo_(T x)
{
// do something with 'x'
}
int foo ()
{
foo_(bar());
}
auto
указывается в терминах вывода типа, поэтому приведенное выше должно иметь очень сходную, если не идентичную семантику, как версию С++ '11.