Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why automatic type inference from the initialization list doesn't work in the constructor?

Why can't I create an instance of a class initialized with an initialization list in the constructor of another class without explicitly specifying the type?

#include <map>
#include <optional>
#include <string>

int main()
{
    std::map<std::string, int> m1({{"test1", 1}, {"test2", 2}, {"test3", 3}});
    std::map<std::string, int> m2{{"test1", 1}, {"test2", 2}, {"test3", 3}};
    auto m3 = std::map<std::string, int>({{"test1", 1}, {"test2", 2}, {"test3", 3}});

    using map_type = std::pair<const std::string, int>;
    std::optional<std::map<std::string, int>>omt1(std::in_place ,{map_type{"test1", 1}, map_type{"test2", 2}, map_type{"test3", 3}});
    std::optional<std::map<std::string, int>>omt2{std::in_place ,{map_type{"test1", 1}, map_type{"test2", 2}, map_type{"test3", 3}}};
    auto omt3 = std::optional<std::map<std::string, int>>(std::in_place ,{map_type{"test1", 1}, map_type{"test2", 2}, map_type{"test3", 3}});


    std::optional<std::map<std::string, int>>om1(std::in_place ,{{"test1", 1}, {"test2", 2}, {"test3", 3}});
    std::optional<std::map<std::string, int>>om2{std::in_place ,{{"test1", 1}, {"test2", 2}, {"test3", 3}}};
    auto om3 = std::optional<std::map<std::string, int>>(std::in_place ,{{"test1", 1}, {"test2", 2}, {"test3", 3}});

    return 0;
}

compiller error:

main.cpp:18:107: error: no matching function for call to ‘std::optional, int> >::optional(const std::in_place_t&, )’
   18 |     std::optional<std::map<std::string, int>>om1(std::in_place ,{{"test1", 1}, {"test2", 2}, {"test3", 3}});
      |                                                                                                           ^
like image 927
Maxim Avatar asked Feb 07 '26 22:02

Maxim


1 Answers

You can make use of the (C++17) deduction guides for std::optional as follows:

std::optional o(
  std::map<std::string, int>{{"test1", 1}, {"test2", 2}, {"test3", 3}}
);

Live demo: https://godbolt.org/z/rfK3WxYqT

The type of the map is written only once, and there is no need for your map_type.


UPDATE

As already mentioned, the problem with your definition:

std::optional<std::map<std::string, int>> om1(
  std::in_place ,{{"test1", 1}, {"test2", 2}, {"test3", 3}}
);

is that a compiler is not able to deduce the template argument for std::initializer_list. A simple demo of this problem:

template <typename T>
void f(std::initializer_list<T>) { }

int main()
{
  f({1, 2, 3});  // OK; T deduced as int
  f({{1, 1}, {2, 2}, {3, 3}}); // ERROR
}

Live demo: https://godbolt.org/z/KofYjdz6v

like image 158
Daniel Langr Avatar answered Feb 09 '26 11:02

Daniel Langr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!