Идентификатор типа std::string для переменной vs. string в аргументе?
Я писал http://en.cppreference.com/w/cpp/language/typeid для написания кода, который делает разные вещи для разных типов.
Код приведен ниже, и пояснение дано в комментариях.
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
void test_template(const T &t)
{
if (typeid(t) == typeid(double))
cout <<"double\n";
if (typeid(t) == typeid(string))
cout <<"string\n";
if (typeid(t) == typeid(int))
cout <<"int\n";
}
int main()
{
auto a = -1;
string str = "ok";
test_template(a); // Prints int
test_template("Helloworld"); // Does not print string
test_template(str); // Prints string
test_template(10.00); // Prints double
return 0;
}
Почему test_template(str)
печатает "string", тогда как test_template("Helloworld")
не работает?
BTW, моя версия g++ - g++ (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.4) 5.4.0 20160609.
Ответы
Ответ 1
В этом вызове
test_template("Helloworld"); // Does not print string
аргумент "Helloworld"
является строковым литералом, который имеет тип const char[11]
.
Поскольку параметр функции является ссылочным типом
void test_template(const T &t)
^^^
то внутри функции аргумент (точнее параметр) имеет тип const char ( &t )[11]
.
Строковые литералы в С++ имеют типы постоянных массивов символов с числом элементов, равным количеству символов в строковом литерале плюс нулевой конец.
В этом вызове
test_template(str);
аргумент имеет тип std::string
, потому что переменная str
объявляется как
string str = "ok";
^^^^^^
Он был инициализирован строковым литералом "ok"
, тем не менее сам объект имеет тип std::string
.
Ответ 2
Строковые литералы в С++ имеют тип const char[N+1]
, где N
- количество символов в строке. std::string
- стандартный класс библиотеки, который владеет строкой и выполняет несколько операций над ней. A std::string
можно построить из a const char[N]
, но они не одно и то же.
Ответ 3
Строковые литералы, такие как "Helloworld"
, представляют собой массивы констант символов.
Класс std::string
имеет конструктор, который может принимать указатели на строковые литералы, но строковый литерал сам по себе не является объектом std::string
.
Как побочная заметка, использование такой функции, как ваш, считается запахом кода и плохим дизайном. Используйте перегруженные функции вместо разных аргументов. Это также решит вашу проблему со строками.