В этой строке:Каков точный тип "" при выводе `auto`?
auto a = "Hello World";
Что такое точное Тип a
? Я думаю, char[]
или const char* const
, но я не уверен.
В этой строке:Каков точный тип "" при выводе `auto`?
auto a = "Hello World";
Что такое точное Тип a
? Я думаю, char[]
или const char* const
, но я не уверен.
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) используется вместо А для типа удержания
* "вы можете проверить это как' TD
@TonyD указывает, что неполный тип запускает ошибку компилятора, которая выводит тип, используемый для создания экземпляра этого неполного типа. Более удобным решением является 'template
@TonyD это проверка. Не определять TD. Вы будете указывать тип TD во время компиляции как ошибку времени компиляции. – ForEveR
Если вы не имеете основания полагать, что это будет реализация или не-определены, можно просто тест:
#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]
.
Вы можете распечатать тип используя 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;
Используйте C++ filter для разметки имен. В любом случае, typeid не лучший, чтобы показывать типы, поскольку он отбрасывает cv-квалификаторы. – edmz
Вы правы, я этого не знал, меня смутил тот факт, что 'char * b = const_cast
Я бы не рекомендовал typeid.name, которое может возвращать неправильные типы как Scott Meier объясняется в http://www.aristeia.com/TalkNotes/C++TypeDeductionandWhyYouCareCppCon2014.pdf (Слайд 32) – Guillermo
Таким образом, он распадается на 'сопзИте полукокс *' –
Похож 'сопзЬ 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