Какие примеры жадного списка инициализаторов скрываются в стандартной библиотеке?

начиная с 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.
}