According to [range.single.view#3], one of std::ranges::single_view
constructors define as:
template<class... Args> requires constructible_from<T, Args...> constexpr explicit single_view(in_place_t, Args&&... args);
Effects: Initializes
value_
as if by value_{in_place, std::forward<Args>(args)...}
.
Why the standard specifies to use of direct-list-initialization ({}
) to initialize value_
? Why not use direct-initialization (()
) just like std::optional
, std::variant
, and std::any
?
Moreover, std::constructible_from
(std::is_constructible
) specifies that T obj(std::declval<Args>()...)
is well-formed instead of T obj{std::declval<Args>()...}
.
Consider the following:
ranges::single_view<std::vector<int>> sv(std::in_place, 100, 0);
std::cout << sv.begin()->size() << "\n"; // #1
std::optional<std::vector<int>> op(std::in_place, 100, 0);
std::cout << op->size() << "\n"; // #2
Because different initializations are used, #1
will call the std::vector<int>{0, 100}
and print 2
, and #2
will call the std::vector<int>(0, 100)
and print 100
.
Why does the standard specify using curly brace initialization for the underlying value even though it may cause inconsistencies? What is the consideration behind this?