Подтвердить что ты не робот

Идентификатор типа 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.

4b9b3361

Ответ 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.


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