Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't std::initializer_list overloads exist for std::make_unique et al?

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

In N4140, unique.ptr.create std::make_unique is specified as so:

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

  • Remarks: This function shall not participate in overload resolution unless T is not an array.

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

That means implementations are required to use () rather than {} to initialize objects. 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 if {} (inside std::make_unique) was used 211 would be output. Because initializer lists cannot be deduced, std::initializer_list must be explicitly passed in order to get the latter result. The question is, why isn't an overload like this 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;
}

Outputs 211.

I don't consider the reasons "you can write it yourself" or "to avoid bloating the standard" to be very good reasons. Is there any disadvantages to providing this overload?

like image 256
user6319825 Avatar asked Oct 30 '22 03:10

user6319825


1 Answers

I don't know the complete history, but the most likely answer is "nobody proposed it".

Evidence for this is supported by the fact that std::make_unique was only added in C++14, yet std::unique_ptr existed in C++11.

The code and proposals for std::make_shared (which was eventually mirrored in make_unique) existed (in boost) prior to the initializer_list and the initialisation syntax supporting it.

One thing you could do now, is to propose it (and work out the corner cases if there are any, e.g. use SFINAE to remove the overload if the target type doesn't support the initializer_list).

like image 200
Niall Avatar answered Nov 02 '22 10:11

Niall