Какие примеры жадного списка инициализаторов скрываются в стандартной библиотеке?
начиная с C++11, стандартные контейнеры библиотеки и std::string
у конструкторов есть список инициализаторов. Этот конструктор имеет приоритет над другими конструкторами (даже, как указано @JohannesSchaub-litb в комментариях, даже игнорируя другие критерии "наилучшего соответствия"). Это приводит к нескольким известным подводным камням при преобразовании всех в скобки ()
формы конструкторов к их скрепленным версиям {}
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
void print(std::vector<int> const& v)
{
std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
std::cout << "n";
}
void print(std::string const& s)
{
std::cout << s << "n";
}
int main()
{
// well-known
print(std::vector<int>{ 11, 22 }); // 11, 22, not 11 copies of 22
print(std::vector<int>{ 11 }); // 11, not 11 copies of 0
// more surprising
print(std::string{ 65, 'C' }); // AC, not 65 copies of 'C'
}
Я не могу найти третий пример на этом сайте, и вещь появилась в чате Lounge (в обсуждении с @rightfold, @Abyx и @JerryCoffin), несколько удивительная вещь заключается в том, что преобразование std::string
конструктор, принимающий количество и символ для использования {}
вместо ()
, изменяющее свое значение с n
копии персонажа в n
- й символ (обычно из таблицы ASCII), за которым следует другой символ.
это не поймано обычным запретом скобки на сужение конверсий, потому что 65-это постоянное выражение, которое может быть представлено как char и сохранит свое исходное значение при преобразовании обратно в int (§8.5.4/7, пуля 4) (благодаря @JerryCoffin).
вопрос: есть ли еще примеры, скрывающиеся в стандартной библиотеке, где преобразование ()
стиль конструктор {}
style, жадно сопоставляется конструктором списка инициализаторов?
2 ответов
я предполагаю, с вашими примерами для std::vector<int>
и std::string
вы намеревались также покрыть другие контейнеры, например,std::list<int>
, std::deque<int>
, etc. которые имеют ту же проблему, очевидно, как std::vector<int>
. Аналогично,int
не единственный тип, поскольку он также применяется к char
, short
, long
и unsigned
версия (возможно, несколько других интегральных типов).
я думаю, что есть еще std::valarray<T>
но я не уверен, если T
разрешается иметь интегральный тип. Вообще-то, я думаю, это имеют различную семантику:
std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};
есть несколько других стандартных шаблонов классов C++, которые принимают std::initializer_list<T>
в качестве аргумента, но я не думаю, что у любого из них есть перегруженный конструктор, который будет использоваться при использовании скобок вместо скобок.
просто в поисках появления initializer_list
.
-
все последовательности, они имеют конструкторы как вектор:
- очереди
- dynarray
- forward_list
- список
- вектор
valarray
принципу basic_string
-
неупорядоченные коллекции, есть конструктор, который принимает целое число в определите начальное количество ведер.
- данная
- unordered_multiset
Я думаю, что это все.
#include <unordered_set>
#include <iostream>
int main() {
std::unordered_set<int> f (3);
std::unordered_set<int> g {3};
std::cout << f.size() << "/" << g.size() << std::endl; // prints 0/1.
}