from '<brace-enclosed initializer list>' to X: understanding list initialization in constructors

117 Views Asked by At

It seems I don't understand braced init lists at all. Why does the following compile for operator=() (entity e) but not for the constructor (entity f)?

Demo

#include <cstdio>
#include <utility>
#include <string_view>

struct entity
{
    using keyval_t = std::pair<std::string_view, std::string_view>;

    entity() = default;

    entity(keyval_t keyval) {
        printf("our special ctor called!\n");
    }

    auto operator=(keyval_t keyval) {
        printf("our special operator called!\n");   
    }
};

int main()
{
    entity e;
    // entity f = { "Hello", "World"}; <-- doesn't work??

    e = { "Hello", "World" };
}

Bonus question: How do I make it work in both cases?

1

There are 1 best solutions below

0
On BEST ANSWER

std::pair has two member variables, thus two given values should be passes to.

This works

entity f = { {"Hello", "World"} };
             ^________________^  
                 keyval_t
           ^____________________^
          entity::entity(keyval_t)

entity f = { "Hello", "World"}; implies calling a constructor with 2 parameters, that entity does not have. Same as entity f{"Hello", "World"}; or entity f("Hello", "World");.

e = { "Hello", "World" }; is just operator=(keyval_t) call with a keyval_t{"Hello", "World"}, since keyval_t has a constructor with 2 parameters.