STL containers require the stored values to be copy constructible and assignable. const T is obviously not an assignable type for any T, but I tried to use it (just being curious) and found out that it compiles and, moreover, behaves as an assignable type.
vector<const int> v(1);
v[0] = 17;
This successfully runs in Visual Studio 2008 and assigns v[0] to 17.
This is not a bug in the implementation as others have suggested.
Violating the requirements of a C++ Standard Library facility does not render your program ill-formed, it yields undefined behavior.
You have violated the requirement that the value type stored in a container must be copy constructible and assignable (const
types are not assignable, obviously), so your program exhibits undefined behavior.
The applicable language from the C++ Standard can be found in C++03 17.4.3.6 [lib.res.on.functions]:
In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ Standard Library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.
In particular, the effects are undefined in the following cases:
...
- for types used as template arguments when instantiating a template component, if the operations on the type do not implement the semantics of the applicable Requirements subclause.
The Visual C++ Standard Library implementation may do anything with this code, including silently removing or ignoring the const-qualification, and it is still standards-conforming.
This simply shouldn't work. At §23.1 ¶ 3 it's specified, as you said, that objects stored in a container must be CopyConstructible
(as specified at §20.1.3) and Assignable
.
The Assignable
requirements for a type T
are that, being t
and u
of type T
, you can do:
t = u
having a T&
as return value and t
equivalent to u
as postcondition. (§23.1 ¶4)
Thus, const
types are clearly not Assignable
, since doing t = u
would raise a compilation error (§7.1.5.1 ¶5).
I suppose that this is a bug in Microsoft implementation. g++ on Linux emits the typical 25 kajillion-lines template error if you even try to instantiate a vector<const int>
(tested both with and without the -std=c++0x
flag, just in case).
By the way, this is also explained in detail in this IBM FAQ.
In theory, as @James McNellis said, the compiler is not required to blow up on the vector instantiation (if it's undefined behavior anything can happen - including everything working fine); however, on the assignation statement there's a violation of the standard that should produce a compilation error.
In facts, the operator[]
member returns a vector<const int>::reference
; that one is required to be an lvalue of T
(§23.1 ¶5 table 66); since T
is of a const
type, it will be a const
lvalue. So we fall down to (§7.1.5.1 ¶5), which defines code that tries to perform an assignment to a const
element as "ill-formed", and this demands a compilation error or at least a warning, because assignment-to-const
is a diagnosable rule (§1.4 ¶1-2) (no "no diagnostic is required" statement is specified).
Final edit
Actually, @James McNellis is right; once you've invoked undefined behavior by instantiating vector<const int>
, the usual rules stop having value, so the implementation is still standard-conforming whatever it does - including removing the const
from the element type or generating the usual nasal demons.
来源:https://stackoverflow.com/questions/4940419/vc-allows-to-use-const-types-for-stl-containers-why