4

In this line:

auto a = "Hello World";

What is the exact Type of a? I'd guess char[] or const char* const but I'm not sure.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
TNA
  • 2,595
  • 1
  • 14
  • 19
  • 2
    This way it decays to `const char*` – Piotr Skotnicki Aug 19 '15 at 07:35
  • Looks like `const char *`, on my version of g++ (4.8.1), both `typeid(a).name()` and `typeid(const char *).name()` return the same value while `typeid(const char[]).name()` or `typeid(b).name()` (`const char b[] = "Hello World";`) return something else. – Holt Aug 19 '15 at 07:43

3 Answers3

10

N4296 2.13.5/8

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).

But since variable is initialized as in your code it is actually const char*, you can check it like this.

template<typename> struct TD;

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

Here will be compile error in which you can see the actual type of TD instance, something like this with clang

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

N4296 7.1.6.4

If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction.

template<typename> struct TD;

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

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

Both instantiated objects of type TD has type TD<const char*>.

N4926 14.8.2.1

Template argument deduction is done by comparing each function template parameter type (call it P) with the type of the corresponding argument of the call (call it A) as described below.

If P is not a reference type:

If A is an array type, the pointer type produced by the array-to-pointer standard conversion (4.2) is used in place of A for type deduction

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • *"you can check it like this `TD _;`"* - how does that check? Not only is `TD` incomplete such that it can't be defined, but if that's fixed it would work for any type - see [here](http://coliru.stacked-crooked.com/a/4469e06eef32b3b9). – Tony Delroy Aug 19 '15 at 07:53
  • 1
    @TonyD the point is that an incomplete type triggers a compiler error which prints out the type used to instantiate this incomplete type. A more convenient solution is `template void TD() { std::cout<<__PRETTY_FUNCTION__< – Piotr Skotnicki Aug 19 '15 at 07:54
  • @TonyD it is check. Not define TD. You will se type of TD on compile-time as compile-time error. – ForEveR Aug 19 '15 at 07:54
  • @ForEveR Your comment would also be a good Extension to your answer. That would make the answer explain itself. – Werner Henze Aug 19 '15 at 07:59
  • 2
    *"triggers a compiler error which prints out the type used to instantiate this incomplete type"* - oh - I guess that's going to be true of any compiler... neat idea. Cheers. – Tony Delroy Aug 19 '15 at 08:00
  • I usually write something like this: `struct checker{} check;` and then `a=check;` It will trigger error that `checker` cannot be converted into `X` (where `X` is the type of `a`). You can also write `check = a;` .. Use whatever reads good enough to you. – Nawaz Aug 19 '15 at 08:19
2

Unless you've reason to think it'd be implementation or un-defined, can just test:

#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)>();
}

Output:

const char*

Checking that ++a compiles is another clue (it does), and while implementation defined #include <typeinfo> / typeid(a).name() can often help answer such questions.

Change to auto& a and you'll see a changes to const char(&)[12].

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
1

You can print the type of a using typeinfo

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

on gcc it will print

pi is: PKc

which stands for pointer to constant char If you're in Windows the output will be a lot more readable, but you get used to this syntax too.

If you know more or less which type you a re looking for, you can also check if two types are equivalent with:

#include <typeinfo>
std::cout << std::is_same<const char*, decltype(a)>::value << std::endl;
dau_sama
  • 4,247
  • 2
  • 23
  • 30
  • Use c++filt to demangle names. Anyways, typeid isn't the best to show types as it discards cv-qualifiers. – edmz Aug 19 '15 at 08:04
  • You are right, I didn't know that, I got confused by the fact that `char* b = const_cast(a); std::cout << "type is: " << typeid(b).name() << '\n';` outputs `Pc` – dau_sama Aug 19 '15 at 08:06
  • I would not recommend typeid.name which can return wrong types as Scott Meier explains in http://www.aristeia.com/TalkNotes/C++TypeDeductionandWhyYouCareCppCon2014.pdf (Slide 32) – Guillermo May 27 '16 at 15:55