c++std-pairlist-initializationstdinitializerlistbraced-init-list

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


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?


Solution

  • 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.