2016-09-22 5 views
0

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

std::vector<int> s{1, 2, 3}; 

for (auto elem : s) { 
    elem = 5; 
} 

for (auto elem : s) { 
    std::cout << elem << std::endl; 
} 

напечатает

1 
2 
3 

потому что эль имеет типа int, не int&. Было бы неплохо попытаться скомпилировать код и получить тип elem, чтобы поймать такие ошибки раньше.

+0

Не знаете, что вы просите. Любой код, который вы напишете, чтобы убедиться, что «elem» является ссылкой, кажется немного дольше, чем для начала написания «auto && elem». – Barry

+3

Вы можете использовать ['std :: is_reference'] (http://en.cppreference.com/w/cpp/types/is_reference) вместе с [' static_assert'] (http://en.cppreference.com/w/CPP/язык/static_assert). Но он добавляет, что для каждого цикла больше работы, чем просто для того, чтобы начать использовать правильный тип.И нет, нет способа заставить компилятор сделать чек для вас, поскольку назначение не является каким-либо недопустимым. –

+2

Ваш пример выглядит повод для предупреждения компилятора. Например, мой компилятор говорит «предупреждение: переменная« elem »установлена, но не используется'. – Sergey

ответ

5

Классический способ объявить структуру шаблона без определения:

template <typename> struct Debug; 

, а затем использовать его:

template struct Debug<std::string>; 

или

for (auto elem : s) { 
    Debug<decltype(elem)>{}; 

    elem = 5; 
} 

Сообщение об ошибке выглядит

error: explicit instantiation of 'struct Debug<std::__cxx11::basic_string<char> >' before definition of template 
template struct Debug<std::string>; 
       ^~~~~~~~~~~~~~~~~~ 

error: invalid use of incomplete type 'struct Debug<int>' 
     Debug<decltype(e)>{}; 

Demo

Кстати, теперь некоторые Иды показывают тип, когда мышь находится над auto или переменной.

+0

Отлично! Мне это нравится еще лучше - к сожалению, я не смог найти этот тип решения с помощью своего Google-foo :( – hochl

1

На самом деле я только что нашел ответ на мой собственный вопрос:

template<typename T> 
void show_type_abort_helper() 
{ 
    return __PRETTY_FUNCTION__; 
} 

#define show_type_abort(x) show_type_abort_helper< decltype(x) >() 

Использование:

std::vector<int> s{1, 2, 3}; 

for (auto elem : s) { 
    show_type_abort(elem); 
    elem = 5; 
} 

Производит следующее сообщение об ошибке с g++ (версия 6.1.1):

$ g++ test.cpp 
test.cpp: In instantiation of ‘void show_type_abort_helper() [with T = int]’: 
                     ^^^ 
test.cpp:17:9: required from here 
test.cpp:7:12: error: return-statement with a value, in function returning 'void' [-fpermissive] 
    return __PRETTY_FUNCTION__; 

Проверьте вывод на T = int, чтобы увидеть, как компилятор использует int как type. Это похоже на работу с лязгом, а также:

$ clang++-3.8 -std=c++11 test.cpp 
test.cpp:7:5: error: void function 'show_type_abort_helper' should not return a value [-Wreturn-type] 
    return __PRETTY_FUNCTION__; 
    ^ ~~~~~~~~~~~~~~~~~~~ 
test.cpp:17:9: note: in instantiation of function template specialization 'show_type_abort_helper<int>' requested here 
                            ^^^ 
     show_type_abort(elem); 

Изменение в for (const auto& elem : s) дает

with T = const int& 
     ^^^^^^^^^^ 

или

show_type_abort_helper<const int &> 
         ^^^^^^^^^^^ 

Так, кажется, я могу узнать тип во время компиляции и отмены. Это очень пригодилось для очень сложного типа, состоящего из нескольких параметров typedef и шаблонов, где я просто не мог видеть, что происходит.