LINUX.ORG.RU

initializer_list in variadic template

 ,


0

5

Вопрос простой, но я как то не понял.
Почему можно:

    auto lst = {2.5f, 1.5f};
    auto  tpl = std::make_tuple("ololo", 1, lst);
Но нельзя
    auto  tpl = std::make_tuple("ololo", 1, {2.5f, 1.5f});

main.cpp:13:57: error: too many arguments to function 'constexpr std::tuple<typename std::__decay_and_strip<_Elements>::__type ...> std::make_tuple(_Elements&& ...) [with _Elements = {}]' auto tpl = std::make_tuple(«ololo», 1, {2.5f, 1.5f}); ^ In file included from prog.cpp:5:0: /usr/include/c++/5/tuple:966:5: note: declared here make_tuple(_Elements&&... __args) ^

Насколько я понял из http://en.cppreference.com/w/cpp/utility/initializer_list, std::initializer_list неявно конструируется только в строго определённых случаях: в list-initialization (Foo a{...}, Foo a = {...}) и в auto, включая ranged for (auto x = {...}, for (x : {...})). Соответственно, твой случай сюда не входит. В стандарте наверняка написано подробнее, но искать лень.

    auto al = {10, 11, 12};   // special rule for auto

//    templated_fn({1, 2, 3}); // compiler error! "{1, 2, 3}" is not an expression,
                             // it has no type, and so T cannot be deduced
    templated_fn<std::initializer_list<int>>({1, 2, 3}); // OK
    templated_fn<std::vector<int>>({1, 2, 3});           // also OK
slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Да, и правда, похоже на то. Причины не сделать {} выражением правда не ясны (с исключительной обработкой легаси случаев типа инициализаций структур и С-массивов) .

CatsCantFly
() автор топика
Ответ на: комментарий от CatsCantFly

Нет причин.

std::initializer_list очень плохо сделан. Самый большой косяк c++11.

Видимо, просто, кому-то очень захотелось писать std::vector<int> t {1, 2, 3};, а то что оно с остальными плюсами не особо дружить будет, комитет НЕ ПОДУМАЛ.

Kuzy ★★★
()
Ответ на: комментарий от slovazap

В c++11, во избежание проблем с Most Vexing Parse, мы вводим, новый, uniform initialization syntax, теперь, просто вызывая конструктор с `{}` вместо `()`, можно не задумываться о подобном.

Всегда используйте uniform initialization syntax, в Современном C++.

std::vector<int> a {3};
std::cout << a.size() << std::endl; // 1
    
std::vector<int> b (3);
std::cout << b.size() << std::endl; // 3

ОЙ

Kuzy ★★★
()
Последнее исправление: Kuzy (всего исправлений: 3)
Ответ на: комментарий от slovazap

Uniform initialization syntax, не uniform. Если использовать только его, то не сможешь вызвать конструктор вектора с std::size_t.

Вообще, у него самый высокий приоритет в перегрузках. И синтаксис совпадающий с UIS.

Kuzy ★★★
()
Ответ на: комментарий от slovazap

Я хочу открыть документацию, найти нужный мне конструктор и вызвать его.

Я не могу это просто сделать с помощью `{}`. Мне еще нужно посмотреть, есть ли там перегрузка с `std::initializer_list`. Чтобы быть уверенным, что не возникнет коллизий.

И это не единообразный синтаксис. Иногда `()` необходимы.

Kuzy ★★★
()
Последнее исправление: Kuzy (всего исправлений: 3)
Ответ на: комментарий от Kuzy

Как я посмотрю, uniform initialization syntax - это просто большое не нужно. Не приходилось им пользоваться (потому что было не нужно), а видя эти приколы и вряд ли захочу им пользоваться.

invy ★★★★★
()
Ответ на: комментарий от invy

Молодец. Мы очень рады что еще есть такие как ты. Это очень важно для нас.

anonymous
()
Ответ на: комментарий от andreyu

Я везде использую UIS. И хочу вектор с тремя элементами. Мне нужно думать, есть ли у вектора std::initializer_list.

Кстати. А если вектор не int, то мне какие скобки писать?

std::vector<Foo> a {3};
std::cout << a.size() << std::endl; // 3

А если я потом добавлю в Foo конструктор с одним int-ом (не explicit)?

Оно скорее всего даже падать после этого не будет. Просто память будет реаллоцироваться чаще.

Kuzy ★★★
()
Последнее исправление: Kuzy (всего исправлений: 1)
Ответ на: комментарий от eao197

Они это ввели в рамках одного стандарта.

Kuzy ★★★
()
Ответ на: комментарий от Kuzy

Кстати. А если вектор не int, то мне какие скобки писать?

Обернуть 3 в еще одни {}, заодно и компайлтайм ошибку сразу можно будет увидеть.

andreyu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.