Author of P2767R0 here. This is all pedantic how-many-angels-can-dance-on-the-head-of-a-pin stuff, so while I'm going to present my own pedantic answer, please understand that I'm not claiming anyone else's different answer is necessarily wrong. It's all equally irrelevant in practice.
(1) flat_map
itself (the class template) is not a container; it's a container adaptor. Even vector
isn't a container; it's a template for stamping out containers. A "container adaptor," in my worldview, is a template for stamping out containers, where one of the template parameters is itself a container. Compare the usage of "iterator adaptor" (and "view adaptor" in Ranges). "Class template reverse_iterator
is an iterator adaptor," but an object of type reverse_iterator<int*>
is (simply) an iterator. flat_set
is a container adaptor; an object of type flat_set<int>
is (simply) a container.
Notice [vector.overview] doesn't say "Class template vector
is a sequence container..."; it says "A vector
is a sequence container..." That is, an object of type some-specialization-of-vector
is (simply) a container.
"But [sequences.general] says, ‘The headers <array>
, <deque>
, <forward_list>
, <list>
, and <vector>
define class templates that meet the requirements for sequence containers!’ How do you square that with your claim that class templates aren't containers?"
Well, surely you agree that <array>
doesn't define any class templates that meet the sequence-container requirements, right? We can argue about vector<bool>
, but array
definitely isn't a container. So that sentence is wrong on the face of it.
(Meanwhile, TIL that C++23's [vector.bool]/8 implies that the user is allowed to provide "a program-defined specialization" for vector<bool, A>
. Who knows what such a specialization might do!)
(2) As far as I'm concerned, flat_map<int, int>
is a container. As you observed, [flat.map]/2 says explicitly that flat_map
"meets all of the requirements of a container." Sure, on one hand it seems clearly to fail the X::reference
requirement... but on the other hand, the standard says it meets all the requirements! Something's got to give; and I think it makes vastly more sense to assume that the C++98-era [container.reqmts] is out of sync with C++23's reality, than to assume that the C++23-era [flat.map] is out of sync. Someone just needs to update [container.reqmts] to handle the modern possibility of proxy reference types.