title: What does "Assignable" really mean?
body: <p>C++11 removed the requirement that the value type of all containers be CopyConstructible and Assignable (although specific operations on containers may impose these requirements). In theory, that should make it possible to define, for example, <code>std::deque&lt;const Foo&gt;</code>, which was not possible in C++03.</p>
  
  <p>Unexpectedly, gcc 4.7.2 produced its usual vomit of incomprehensible errors [1] when I tried this, but clang at least made the error readable and clang with libc++ compiled it with no errors.</p>
  
  <p>Now, when two different compilers produce different results, it always makes me wonder what the correct answer is, and so I searched out all the references I could find to const/assignable/value types/containers, etc., etc. I found almost a decade's worth of very similar questions and answers, some of them here on SO and others in the various C++ mailing lists, amongst other places, including the Gnu buganizer, all of which basically can be summarized as following dialogue.</p>
  
  <p>Q: Why can't I declare <code>std::vector&lt;const int&gt;</code> (as a simplified example)</p>
  
  <p>A: Why on earth would you want to do that? It's nonsensical.</p>
  
  <p>Q: Well, it makes sense to me. Why can't I do it?</p>
  
  <p>A: Because the Standard requires value types to be assignable.</p>
  
  <p>Q: But I'm not planning on assigning them. I want them to be const after I've created them.</p>
  
  <p>A: That's not the way it works. Next question!</p>
  
  <p>with a mild dashing of:</p>
  
  <p>A2: C++11 has decided to allow that. You'll just have to wait. In the meantime, rethink your ridiculous design.</p>
  
  <p>These don't seem like very compelling answers, although possibly I'm biased because I fall into the category of "but it makes sense to me". In my case, I'd like to have a stack-like container in which things pushed onto the stack are immutable until they are popped, which doesn't strike me as a particularly odd thing to want to be able to express with a type system.</p>
  
  <p>Anyway, I started thinking about the answer, "the standard requires all containers' value types to be assignable." And, as far as I can see, now that I found an old copy of a draft of the C++03 standard, that's true; it did.</p>
  
  <p>On the other hand, the value type of <code>std::map</code> is <code>std::pair&lt;<b>const</b> Key, T&gt;</code> which doesn't look to me like it's assignable. Still, I tried again with <code>std::deque&lt;std::tuple&lt;const Foo&gt;&gt;</code>, and gcc proceeded to compile it without batting an eye. So at least I have some kind of workaround.</p>
  
  <p>Then I tried printing out the value of <code>std::is_assignable&lt;const Foo, const Foo&gt;</code> and <code>std::is_assignable&lt;std::tuple&lt;const Foo&gt;, const std::tuple&lt;const Foo&gt;&gt;</code>, and it turns out that the former is reported as not assignable, as you'd expect, but the latter is reported as assignable (by both clang and gcc). Of course, it's not really assignable; attempting to compile <code>a = b;</code> is rejected by gcc with the complaint <code>error: assignment of read-only location</code> (this was just about the only error message I encountered in this quest which was actually easy to understand). However, without the attempt to do an assignment, both clang and gcc are equally happy to instantiate the <code>deque&lt;const&gt;</code>, and the code seems to run fine.</p>
  
  <p>Now, if <code>std::tuple&lt;const int&gt;</code> really is assignable, then I can't complain about the inconsistency in the <code>C++03</code> standard -- and, really, who cares -- but I find it disturbing that two different standard library implementations report that a type is assignable when in fact, attempting to assign to a reference of it will lead to a (very sensible) compiler error. I might at some point want to use the test in a template SFINAE, and based on what I saw today, it doesn't look very reliable.</p>
  
  <p>So is there anyone who can shed some light on the question (in the title): <em>What does Assignable really mean?</em> And two bonus questions:</p>
  
  <p>1) Did the committee really mean to allow instantiating containers with <code>const</code> value types, or did they have some other non-assignable case in mind?, and</p>
  
  <p>2) Is there really a significant difference between the constnesses of <code>const Foo</code> and <code>std::tuple&lt;const Foo&gt;</code>?</p>
  
  <hr>
  
  <p>[1] For the truly curious, here's the error message produced by gcc when trying to compile the declaration of <code>std::deque&lt;const std::string&gt;</code> (with a few line-endings added, and an explanation if you scroll down far enough):</p>
  
  <pre><code>In file included from /usr/include/x86_64-linux-gnu/c++/4.7/./bits/c++allocator.h:34:0,
                   from /usr/include/c++/4.7/bits/allocator.h:48,
                   from /usr/include/c++/4.7/string:43,
                   from /usr/include/c++/4.7/random:41,
                   from /usr/include/c++/4.7/bits/stl_algo.h:67,
                   from /usr/include/c++/4.7/algorithm:63,
                   from const_stack.cc:1:
  /usr/include/c++/4.7/ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator&lt;const std::basic_string&lt;char&gt; &gt;’:
  /usr/include/c++/4.7/bits/allocator.h:89:11:   required from ‘class std::allocator&lt;const std::basic_string&lt;char&gt; &gt;’
  /usr/include/c++/4.7/bits/stl_deque.h:489:61:   required from ‘class std::_Deque_base&lt;const std::basic_string&lt;char&gt;, std::allocator&lt;const std::basic_string&lt;char&gt; &gt; &gt;’
  /usr/include/c++/4.7/bits/stl_deque.h:728:11:   required from ‘class std::deque&lt;const std::basic_string&lt;char&gt; &gt;’
  const_stack.cc:112:27:   required from here
  /usr/include/c++/4.7/ext/new_allocator.h:83:7:
    error: ‘const _Tp* __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::address(
    __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::const_reference) const [
    with _Tp = const std::basic_string&lt;char&gt;;
    __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::const_pointer =
      const std::basic_string&lt;char&gt;*;
    __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::const_reference =
      const std::basic_string&lt;char&gt;&amp;]’ cannot be overloaded
  /usr/include/c++/4.7/ext/new_allocator.h:79:7:
    error: with ‘_Tp* __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::address(
    __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::reference) const [
    with _Tp = const std::basic_string&lt;char&gt;;
    __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::pointer = const std::basic_string&lt;char&gt;*;
    __gnu_cxx::new_allocator&lt; &lt;template-parameter-1-1&gt; &gt;::reference = const std::basic_string&lt;char&gt;&amp;]’
  </code></pre>
  
  <p>So what's going on here is that the standard (&sect; 20.6.9.1) insists that the default allocator have member functions:</p>
  
  <pre><code>pointer address(reference x) const noexcept;
  const_pointer address(const_reference x) const noexcept;
  </code></pre>
  
  <p>but if you instantiate it with a <code>const</code> template argument (which is apparently UB), then <code>reference</code> and <code>const_reference</code> are the same type, and so the declarations are duplicated. (The body of the definition is identical, for what it's worth.) Consequently, no allocator-aware container can deal with an explicitly <code>const</code> value type. Hiding the <code>const</code> inside a <code>tuple</code> allows the allocator to instantiate. This allocator requirement from the standard was used to justify closing at least a couple of old libstdc++ bugs about problems with  <code>std::vector&lt;const int&gt;</code>, although it doesn't strike me as a solid point of principle. Also libc++ works around the problem in the obvious simple way, which is to provide a specialization of <code>allocator&lt;const T&gt;</code> with the duplicate function declarations removed.</p>