rampion rampion - 3 months ago 10
C++ Question

Use string's fill constructor with an initializer list

I'm reading through Ivor Horton's "Beginning C++". In Chapter 7, there's this example on string initialization:


However, you can initialize a string with any number of instances of given character. You can define and initialize a sleepy time
string
object like this:

string sleeping {6, 'z'};


The
string
object,
sleeping
, will contain
"zzzzzz"
. The string length will be 6.


With my compiler,
Apple LLVM version 6.0 (clang-600.0.57)
, the example doesn't work as described. Instead, it works as if I'd given:

string sleeping {"\6z"};


Using
string
's "from c-string" constructor, rather than its "fill" constructor
.

I know I can use the fill constructor by using parens:

string sleeping(6, 'z');


But just to satisfy my curiosity, is there any way to use the fill constructor with an initializer list, as in the book example?

Answer

No, this is not possible, the standard specifies it:

  • If T is an aggregate type [...];
  • Otherwise, if T is a character array [...];
  • If T is an aggregate type [...];
  • Otherwise, If the braced-init-list is empty [...];
  • Otherwise, the constructors of T are considered, in two phases:
    • 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

So the constructor of std::string that takes an std::initializer_list as its first arguments will always be considered before the ones that takes a count and a character.

The only way to use list-initialization with this constructor would be to also provide the allocator:

std::string s{6, 'z', std::string::allocator_type{}};