Allocate vector size with list initialization (curly braces)
Asked Answered
D

2

19

How can I do the equivalent of:

#include <vector>

size_t bufferSize = 1024 * 1024;
std::vector<unsigned char> buffer(bufferSize, ' ');

With list (curly braced) initialization?

When I try to do the following:

#include <vector>

size_t bufferSize = 1024 * 1024;
std::vector<unsigned char> buffer {bufferSize, ' '};

It wrongly interprets bufferSize as the value to be stored in the first index of the container (i.e. calls the wrong std::vector constructor), and fails to compile due to invalid narrowing conversion from unsigned int (size_t) to unsigned char.

Demilune answered 29/11, 2018 at 15:4 Comment(13)
That's how brace-initialization works with std::initializer_list constructors. It always prefer those constructors, hence it tries to invoke it and failsJackelynjackeroo
Why do you insist on doing this with "curly brace initialization"?Faldstool
Basically a dupe of: #47775939Catanzaro
You cannot and it is big downside of idea "use curly brackets initialization everywhere". If would just use bufferSize issue would be even worseBeauvoir
@MaxLanghof Well, it is called uniform initialization. One could be lead to believe it should be the preferred way to initialize an object ;)Catanzaro
@Catanzaro Well I never quite got why C++ insisted on doing this to C++ initialization...Faldstool
@Catanzaro Related xkcd.com/927Backstage
@OP Here is a very good talk on the nightmare of C++ initialization: youtube.com/watch?v=7DTlWPgX6zsCatanzaro
@MaxLanghof because some recommend to use it everywhere as it is "safer" (does not have most vexing parse issue). In reality it is more dangerous.Beauvoir
Lately I've gotten into the habit of using auto var = type(stuff); as it is easier for me to control which constructor I want to call. One of these days we might actually get this fixed though.Catanzaro
Related #33445314Beauvoir
tldr; Use vector{...} to initialize from a list (including 0 elements), and vector(...) to call all other constructors. "Universal" doesn't mean "this is the replacement". It just means you can now list initialize on all objects, rather than just some of them.Commemoration
@MaxLanghof another reason for wanting to use curly brace initialization is non-static member initialization via a default member initializer which is either a brace or equal initializer. And when a - say - std::vector<int> member should be constructed with a certain size, one can't just write something as compact as std::vector<int> foo { some_size, 42 } which actually creates the vector member with some_size elements which are initialized to 42.Sheilahshekel
I
18

Short answer: you don't.

This is not a problem with uniform initialization per se, but with std::initializer_list. There is a special rule in overload resolution that always gives priority to constructors taking std::initializer_list if list-initialization is used, regardless of the existence of other constructors which might require less implicit conversions.


I would suggest using

std::vector<unsigned char> buffer(bufferSize, ' ');

or, if you really want to use list-initialization, create your wrapper around std::vector that provides constructor overloads that do the right thing.

Inactivate answered 29/11, 2018 at 15:19 Comment(0)
B
7

The two relevant overload of std::vector are:

explicit vector( size_type count, 
                 const T& value = T(),
                 const Allocator& alloc = Allocator()); //(1)
vector( std::initializer_list<T> init, 
        const Allocator& alloc = Allocator() ); // (2)

These two overload has clear meaning, where the second is used to initialize the vector with the elements of the std::initializer_list.

Overload resolution prefer initializer-list constructors when list-initialization is used.

Narrowing conversions are not allowed with list-initialization, you're trying to create a std::vector with T=unsigned char but the deduced T for the std::initializer_list parameter is T= unsigned long which will involve a narrowing conversion (not allowed).

Bellicose answered 29/11, 2018 at 15:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.