title: Getting non-const iterator using declval
body: <p>A minimal example that shows two ways of getting an iterator type that I would naively expect to give the same type as a result:</p>
  
  <pre><code>template &lt;typename Range&gt;
  struct foo
  {
      using iterator = decltype(std::begin(std::declval&lt;Range&gt;()));
      using iterator2 = typename Range::iterator;
  
      static_assert(std::is_same&lt;iterator, iterator2&gt;::value, "Iterator types differ!");
  };
  
  int main()
  {
      std::vector&lt;int&gt; v;
      foo&lt;decltype(v)&gt; f;
  }
  </code></pre>
  
  <p>But this actually triggers the static assert.</p>
  
  <p>If we change the first iterator to:</p>
  
  <pre><code>using iterator = decltype(std::declval&lt;Range&gt;().begin());
  </code></pre>
  
  <p>no static assert is fired.</p>
  
  <p>Looking at the definition of <code>std::begin()</code>, this is overloaded for both reference and const-reference types. Since <code>declval</code> gives back an rvalue-reference, this will only bind to a const reference, thus giving back a const iterator type.</p>
  
  <p>This can be worked around with something of an abomination, using reference collapsing:</p>
  
  <pre><code>using iterator = decltype(std::begin(std::declval&lt;typename std::add_lvalue_reference&lt;Range&gt;::type&gt;()));
  </code></pre>
  
  <p>Is there an easier way of getting a non-const iterator? Obviously <code>typename Range::iterator</code> isn't going to exist for all types (e.g. <code>T*</code>), and likewise for the member <code>begin()</code>, thus neither are ideal.</p>