вывод типа для std :: initializer_list

Если я напишу это

std::vector<std::string> v{"one","two","three"};

Какой тип выведен для ассоциированного std::initializer_list шаблон?
Другими словами, когда char * строковые литералы преобразуются в std::string ?

Лучше объявить это как

std::vector<std::string> v{std::string("one"),
std::string("two"),
std::string("three")};

чтобы избежать проблем, связанных с механизмом определения типа используемых шаблонов?
Я буду придерживаться той же оптимизации с этим?

0

Решение

Обновить: Чтобы ответить на ваш вопрос о типе вывод:
Конструктор списка инициализатора vector<string> занимает initializer_list<string>, Это не шаблонно, поэтому ничего не происходит с точки зрения вывода типа.

Тем не менее, тип преобразование и правила разрешения перегрузки, применяемые здесь, представляют некоторый интерес, поэтому я оставлю свой первоначальный ответ в силе, так как вы уже приняли его:

Оригинальный ответ:

Сначала компилятор видит только список инициализаторов {"one","two","three"}, который является только списком инициализаторов, но еще не является объектом типа std::initializer_list,

Затем он пытается найти подходящего конструктора vector<string> чтобы соответствовать этому списку.
Как это сделать, это довольно сложный процесс, вам лучше всего посмотреть в самом стандарте, если вы заинтересованы в точном процессе.

Поэтому компилятор решает создать фактический объект std::initializer_list<string> от список инициализаторов, поскольку неявное преобразование из char*к std::strings делает это возможным.

Еще один, может быть, более интересный пример:

std::vector<long>   vl1{3};
std::vector<string> vs1{3};
std::vector<string> vs2{0};

Что они делают?

  1. Первая строка относительно проста. список инициализаторов {3} может быть преобразован в std::initializer_list<long> аналогично {"onm", "two", "three"} Пример выше, так что вы получите вектор с одним элементом, который имеет значение 3.

  2. Вторая строка отличается. Он строит вектор из 3 пустых строк. Зачем? Потому что список инициализаторов {3} ни в коем случае не может быть преобразован в std::initializer_list<string>так что «нормальный» конструктор std::vector<T>::vector(size_t, T = T()) включается и дает три строки по умолчанию.

  3. Ну, этот должен быть примерно таким же, как второй, верно? Другими словами, он должен давать пустой вектор с нулевыми строками по умолчанию. НЕПРАВИЛЬНО!. 0 может рассматриваться как константа нулевого указателя, и проверяет std::initializer_list<string>, Только на этот раз единственная строка в этом списке создается нулевым указателем, что недопустимо, поэтому вы получаете исключение.

7

Другие решения

Вывод типа отсутствует, поскольку вектор предоставляет только полностью специализированный конструктор со списком инициализаторов. Мы могли бы добавить шаблонную косвенность, чтобы играть с выводом типа. Пример ниже показывает, что std::initializer_list<const char*> является недопустимым аргументом для векторного конструктора.

#include <string>
#include <vector>

std::string operator"" _s( const char* s, size_t sz ) { return {s, s+sz}; }

template<typename T>
std::vector<std::string> make_vector( std::initializer_list<T> il ) {
return {il};
}

int main() {
auto compile = make_vector<std::string>( { "uie","uieui","ueueuieuie" } );
auto compile_too = make_vector<std::string>( { "uie"_s, "uieui", "ueueuieuie" } );
//auto do_not_compile = make_vector( { "uie","uieui","ueueuieuie" } );
}

Живая демо

3

От http://en.cppreference.com/w/cpp/language/string_literal:

Тип строкового литерала без префикса const char[]

Таким образом, дела идут так:

#include <iostream>
#include <initializer_list>
#include <vector>
#include <typeinfo>
#include <type_traits>
using namespace std;

int main() {
std::cout << std::boolalpha;
std::initializer_list<char*> v = {"one","two","three"}; // Takes string literal pointers (char*)
auto var = v.begin();
char *myvar;
cout << (typeid(decltype(*var)) == typeid(decltype(myvar))); // true

std::string ea = "hello";
std::initializer_list<std::string> v2 = {"one","two","three"}; // Constructs 3 std::string objects
auto var2 = v2.begin();
cout << (typeid(decltype(*var2)) == typeid(decltype(ea))); // true
std::vector<std::string> vec(v2);
return 0;
}

http://ideone.com/UJ4a0i

2
По вопросам рекламы [email protected]