Container requirements have changed from C++03 to C++11. While C++03 had blanket requirements (e.g. copy constructibility and assignability for vector), C++11 defines fine-grained requirements on each container operation (section 23.2).
As a result, you can e.g. store a type that is copy-constructible but not assignable - such as a structure with a const member - in a vector as long as you only perform certain operations that do not require assignment (construction and push_back
are such operations; insert
is not).
What I'm wondering is: does this mean the standard now allows vector<const T>
? I don't see any reason it shouldn't - const T
, just like a structure with a const member, is a type that is copy constructible but not assignable - but I may have missed something.
(Part of what makes me think I may have missed something, is that gcc trunk crashes and burns if you try to instantiate vector<const T>
, but it's fine with vector<T>
where T has a const member).
No, I believe the allocator requirements say that T can be a "non-const, non-reference object type".
You wouldn't be able to do much with a vector of constant objects. And a const vector<T>
would be almost the same anyway.
Many years later this quick-and-dirty answer still seems to be attracting comments and votes. Not always up. :-)
So to add some proper references:
For the C++03 standard, which I have on paper, Table 31 in section [lib.allocator.requirements] says:
T, U any type
Not that any type actually worked.
So, the next standard, C++11, says in a close draft in [allocator.requirements] and now Table 27:
T, U, C any non-const, non-reference object type
which is extremely close to what I originally wrote above from memory. This is also what the question was about.
However, in C++14 (draft N4296) Table 27 now says:
T, U, C any non-const object type
Possibly because a reference perhaps isn't an object type after all?
And now in C++17 (draft N4659) it is Table 30 that says:
T, U, C any cv-unqualified object type (6.9)
So not only is const
ruled out, but also volatile
. Probably old news anyway, and just a clarification.
Please also see Howard Hinnant's first-hand info, currently right below.
Update
Under the accepted (and correct) answer I commented in 2011:
Bottom line: We didn't design containers to hold
const T
. Though I did give it some thought. And we came really close to doing it by accident. To the best of my knowledge, the current sticking point is the pair of overloadedaddress
member functions in the default allocator: WhenT
isconst
, these two overloads have the same signature. An easy way to correct this would be to specializestd::allocator<const T>
and remove one of the overloads.
With the upcoming C++17 draft it appears to me that we have now legalized vector<const T>
, and I also believe we've done it accidentally. :-)
P0174R0 removes the address
overloads from std::allocator<T>
. P0174R0 makes no mention of supporting std::allocator<const T>
as part of its rationale.
Correction
In the comments below T.C. correctly notes that the address
overloads are deprecated, not removed. My bad. The deprecated members don't show up in in 20.10.9 where the std::allocator
is defined, but are instead relegated to section D.9. I neglected to scan Chapter D for this possibility when I posted this.
Thank you T.C. for the correction. I contemplated deleting this misleading answer, but perhaps it is best to leave it up with this correction so that perhaps it will keep someone else from misreading the spec in the same way I did.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With