Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VC++ allows to use const types for STL containers. Why?

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.

like image 601
lizarisk Avatar asked Feb 09 '11 01:02

lizarisk


People also ask

What are the types of STL containers?

In C++, there are generally 3 kinds of STL containers: Sequential Containers. Associative Containers. Unordered Associative Containers.

When should you use const C++?

The const keyword allows you to specify whether or not a variable is modifiable. You can use const to prevent modifications to variables and const pointers and const references prevent changing the data pointed to (or referenced).

What do all STL containers define?

An STL container is a collection of objects of the same type (the elements). Container owns the elements. Creation and destruction is controlled by the container.


2 Answers

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.

like image 104
James McNellis Avatar answered Sep 20 '22 11:09

James McNellis


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.

like image 42
Matteo Italia Avatar answered Sep 20 '22 11:09

Matteo Italia