Programming
c++ c++11 vector list-initialization
Updated Mon, 19 Sep 2022 07:04:48 GMT

List initialization rules


I want to initialize std::vector<char> with count and value.

This works:

int n = 100;
std::vector<char> v(n, 0);

However, list initialization std::vector<char> v{n, char(0)}; gives me:

warning: narrowing conversion of n from int to char.

Is there a way to use list initialization syntax but avoid initializer_list constructor called?




Solution

Unfortunately, no.

When you're to list-initialize a std::vector, it'll first try to use the constructor with the std::initializer_list parameter. Other constructors will be considered only if there's no suitable match.

Quoted from cppref

  • All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
  • If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all).

In your case, since type conversion between char and int is allowed, the constructor with std::initializer_list is used.

My suggestion for initialization a std::vector(and other containers) is don't use list-initialization unless you're initialized with a std::initializer_list and use copy-list-initialization only.

struct A {};
std::vector<A> v1{100}; // ok, the size of v1 is 100
std::vector<A> v2(100); // better, the size of v2 is 100
std::vector<A> v3 = {100}; // compiles error