Why are there no overloads of std :: initializer_list for std :: make_unique and others?

See Should I use () or {} when passing arguments? . foo is a clone of std::vector .

In N4140 unique.ptr.create std::make_unique specified like this:

template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);

  • Notes: This function should not participate in overload resolution if T not an array.

  • Returns: unique_ptr<T>(new T(std::forward<Args>(args)...)) .

This means that to initialize objects for implementation, you must use () instead of {} . As an example, the following

 auto s1 = std::make_unique<foo>(3, 1).get()->size(); auto s2 = std::make_unique<foo>(1).get()->size(); auto s3 = std::make_unique<foo>(2).get()->size(); std::cout << s1 << s2 << s3; 

outputs 312 , whereas when using {} (inside std::make_unique ) 211 will be output. Since initializer lists cannot be displayed, std::initializer_list must be explicitly passed in order to get the last result. The question is, why is not the overload as provided?

 namespace test { template <class T, class Deduce> std::unique_ptr<T> make_unique(std::initializer_list<Deduce> li) { return ::std::make_unique<T>(li); } }; int main() { auto p1 = test::make_unique<foo>({3, 1}).get()->size(); auto p2 = test::make_unique<foo>({1}).get()->size(); auto p3 = test::make_unique<foo>({2}).get()->size(); std::cout << p1 << p2 << p3; } 

Conclusion 211 .

I do not consider the reasons “you can write yourself” or “to avoid inflating the standard”, to be very good reasons. Are there any flaws in providing this overload?

+5
source share
2 answers

I do not know the full story, but the most likely answer is "no one suggested."

The evidence for this is confirmed by the fact that std::make_unique was only added in C ++ 14, but std::unique_ptr existed in C ++ 11.

The code and suggestions for std::make_shared (which was eventually reflected in make_unique ) existed (in boost) before initializer_list and the initializer_list syntax that supports it.

One thing you could do now is to suggest it (and work out the angular cases, if any, for example, use SFINAE to remove the overload if the target type does not support initializer_list ).

+2
source

I think this is just a problem with subtracting the template, see this answer .

You can try:

 int main() { auto p1 = std::make_unique<foo>(std::initializer_list<int>{3, 1}).get()->size(); auto p2 = std::make_unique<foo>(foo{1}).get()->size(); auto l3 = {2}; auto p3 = std::make_unique<foo>(l3).get()->size(); std::cout << p1 << p2 << p3; } 
0
source

All Articles