Initializing container of unique_ptrs from initializer list fails with GCC 4.7

前端 未结 2 1465
隐瞒了意图╮
隐瞒了意图╮ 2020-11-30 04:36

I am trying to initialise an std::vector> in a way that is equivalent to an example from Bjarne Stroustrup\'s C++11 FAQ

相关标签:
2条回答
  • 2020-11-30 05:10

    After "fixing" your example:

    #include <vector>
    #include <memory>
    #include <string>
    
    int main()
    {
        std::vector<std::unique_ptr<std::string>> vs = { { new std::string{"Doug"} }, { new std::string{"Adams"} } }; // fails
        std::unique_ptr<std::string> ps { new std::string{"42"} }; // OK
    }
    

    I got very a clear error message:

    error: converting to 'std::unique_ptr<std::basic_string<char> >' from initializer list would use explicit constructor 'std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = std::basic_string<char>, _Dp = std::default_delete<std::basic_string<char> >, std::unique_ptr<_Tp, _Dp>::pointer = std::basic_string<char>*]'
    

    This error tells us that it is not possible to use the unique_ptr's explicit contructor!

    0 讨论(0)
  • 2020-11-30 05:18

    unique_ptr's constructor is explicit. So you can't create one implicitly with from new string{"foo"}. It needs to be something like unique_ptr<string>{ new string{"foo"} }.

    Which leads us to this

    // not good
    vector<unique_ptr<string>> vs {
        unique_ptr<string>{ new string{"Doug"} },
        unique_ptr<string>{ new string{"Adams"} }
    };
    

    However it may leak if one of the constructors fails. It's safer to use make_unique:

    // does not work
    vector<unique_ptr<string>> vs {
         make_unique<string>("Doug"),
         make_unique<string>("Adams")
    };
    

    But... initializer_lists always perform copies, and unique_ptrs are not copyable. This is something really annoying about initializer lists. You can hack around it, or fallback to initialization with calls to emplace_back.

    If you're actually managing strings with smart pointers and it's not just for the example, then you can do even better: just make a vector<string>. The std::string already handles the resources it uses.

    0 讨论(0)
提交回复
热议问题