2015-08-19 1 views
4

В этой строке:Каков точный тип "" при выводе `auto`?

auto a = "Hello World"; 

Что такое точное Тип a? Я думаю, char[] или const char* const, но я не уверен.

+2

Таким образом, он распадается на 'сопзИте полукокс *' –

+0

Похож 'сопзЬ char * ', в моей версии g ++ (4.8.1), и' typeid (a) .name() 'и' typeid (const char *). name() 'возвращает одно и то же значение, а' typeid (const char [ ]). name() 'или' typeid (b) .name() '(' const char b [] = "Hello World"; ') возвращает что-то еще. – Holt

ответ

10

N4296 2.13.5/8

Обычные строковые литералы и UTF-8, строковые литералы также называют как узкие строковые литералы. Узкий строковый литерал имеет тип «массив из n const char», где n - размер строки, как определено ниже, и имеет статическую продолжительность хранения (3.7).

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

template<typename> struct TD; 

int main() 
{ 
    auto a = "Hello World"; 
    TD<decltype(a)> _; 
} 

Здесь будет ошибка компиляции, в которой вы можете увидеть фактический тип TD например, что-то подобное с лязгом

error: implicit instantiation of undefined template 'TD<const char *>' 

N4296 7.1.6.4

Если заполнитель автоматический тип-спецификатор, выводимый тип - , определяемый с использованием правил вывода аргумента шаблона.

template<typename> struct TD; 

template<typename T> 
void f(T) 
{ 
    TD<T> _; 
} 

int main() 
{ 
    auto c = "Hello"; 
    TD<decltype(c)> _; 
    f("Hello"); 
} 

Оба воплощенные объекты типа TD имеет тип TD<const char*>.

N4926 14.8.2.1

аргумент шаблона вычет делается путем сравнения каждой функции шаблона типа параметра (назовем его P) с типом соответствующего аргумента вызова (назовем его А), как описано ниже.

Если P не является тип ссылки:

Если A представляет собой тип массива, тип указателя производится с помощью массива к-указателя стандартного преобразования (4.2) используется вместо А для типа удержания

+0

* "вы можете проверить это как' TD _; '" * - как это проверить? Мало того, что 'TD' является неполным, так что он не может быть определен, но если он исправлен, он будет работать для любого типа - см. [Здесь] (http://coliru.stacked-crooked.com/a/4469e06eef32b3b9). –

+1

@TonyD указывает, что неполный тип запускает ошибку компилятора, которая выводит тип, используемый для создания экземпляра этого неполного типа. Более удобным решением является 'template void TD() {std :: cout << __ PRETTY_FUNCTION __ << std :: endl; } ' –

+0

@TonyD это проверка. Не определять TD. Вы будете указывать тип TD во время компиляции как ошибку времени компиляции. – ForEveR

2

Если вы не имеете основания полагать, что это будет реализация или не-определены, можно просто тест:

#include <iostream> 

template <typename T> void f() { std::cout << "other\n"; } 
template <> void f<const char*>() { std::cout << "const char*\n"; } 
template <> void f<const char* const>() 
    { std::cout << "const char* const\n"; } 
template <> void f<const char(&)[12]>() { std::cout << "const char[12]\n"; } 

int main() 
{ 
    auto a = "Hello World"; 
    f<decltype(a)>(); 
} 

Выход:

const char* 

Проверка, что ++a компилирует еще один ключ (он делает), и в то время как реализация определяется #include <typeinfo>/typeid(a).name() часто может помочь ответить на такие вопросы.

Изменить на auto& a, и вы увидите a Изменения в const char(&)[12].

1

Вы можете распечатать тип используя typeinfo

int main() 
{ 
    auto a = "Hello World"; 
    std::cout << "type is: " << typeid(a).name() << '\n'; 
} 

на GCC будет печатать

Пи: PKc

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

Если вы знаете больше или меньше, какой тип вам ищет, вы также можете проверить, если два типа эквивалентен:

#include <typeinfo> 
std::cout << std::is_same<const char*, decltype(a)>::value << std::endl; 
+0

Используйте C++ filter для разметки имен. В любом случае, typeid не лучший, чтобы показывать типы, поскольку он отбрасывает cv-квалификаторы. – edmz

+0

Вы правы, я этого не знал, меня смутил тот факт, что 'char * b = const_cast (a); std :: cout << "type is:" << typeid (b) .name() << '\ n'; 'выходы' Pc' –

+0

Я бы не рекомендовал typeid.name, которое может возвращать неправильные типы как Scott Meier объясняется в http://www.aristeia.com/TalkNotes/C++TypeDeductionandWhyYouCareCppCon2014.pdf (Слайд 32) – Guillermo

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