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?