On Sat, Mar 11, 2023 at 7:34 AM LoS via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
I noticed that C++23 added new overloaded constructors for the std::stack and std::queue container adapters, that allow to construct the underlying container with the contents of the range [first, last). [...]
However, C++23 also added other container adapters (std::flat_set, std::flat_multiset, std::flat_map, std::flat_multimap), that provides the following overloaded constructors:
[...]
template<class Allocator>
/* flat_container */ (initializer_list<key_type> il, const Allocator& a);

I did not find a specific reason therefore the overloaded constructors were introduced in these group of container adapters but not in the others.

Coincidentally, I just mentioned the difficulty of adding non-explicit ctor overloads yesterday (to container adaptors, no less) in
https://quuxplusone.github.io/draft/d2447-std-span-over-initializer-list.html#annex-c

I think priority_queue should get an initializer_list ctor, because we all know what priority_queue<int> pq = {1,2,3} ought to do.
I think queue probably should get an initializer_list ctor, because I assume we all know what queue<int> q = {1,2,3} ought to do: items pop from the front of the queue, so "1" would be at the front, right?
I'm more skeptical of `stack`. I don't think anyone would guess better than 50/50 what stack<int> st = {1,2,3} ought to do, as written. Items pop from the "top" of a stack, yes, but is that the left end or the right end? (Experts know it must be the right end because that's the only efficient end when the container is a vector; but I don't think that's terribly obvious.)  However, on the other hand, it's true that the iterator-pair ctor Does The Right Thing: if you push 1, then 2, then 3, you end up with an underlying vector containing {1,2,3}. So why not just let the programmer write {1,2,3} in the first place? So I'm skeptical, but not completely anti.

Anyway, in all of those cases, adding new ctors will change overload sets — and change them drastically, because initializer_list ctors are even greedier than other non-explicit ctors. (This is why implicit conversions are the devil, and the STL's prevailing style of "make everything implicit unless there's a positive reason to make it explicit" is the Wrong Default as usual. Python got it right.)  So that's probably why LEWG has been leery of doing so.

OTOH, `flat_set` and `flat_map` are completely novel class types; nobody has any existing code that would be broken by fiddling with their overload sets.
And `flat_set` is supposed to be a drop-in replacement for `set`! So obviously it would be a non-starter if you could write
    std::set<int> s = {1,2,3};
but not
    std::flat_set<int> s = {1,2,3};
That just has to work, period.

I'd be mildly interested in coauthoring a paper, but I think it would require you to show actual implementation experience. Consider submitting a patch against my "Quuxplusone/llvm-project" libc++ fork. ;)  That would demonstrate that the overload set is possible in principle, and that it doesn't break any libc++ tests. (Or else, it'll show that it does break things, and maybe answer your question even better.)
https://github.com/llvm/llvm-project/compare/main...Quuxplusone:llvm-project:trivially-relocatable

–Arthur