Search code examples
c++stlstl-algorithm

std::back_inserter needs const_reference on older GCC. Why?


I am currently looking at some code that can be compiled on newer versions of GCC but not on older ones. In my case I am using a std::back_inserter to std::copy some data from one data structure to a custom data structure. If I forget the typedef value_type & const_reference typedef in this custom data structure however, this will not compile on GCC 4.4. The same code compiles and runs just fine on GCC 4.5.

What is the difference in between these two compiler versions, that makes the code compile on one version but not on the other. I would guess it has something to do with the implementation of C++11 which was much less complete in GCC 4.4. Probably something with decltype or another new C++11 keyword, I would guess.

Also is this code correct, if I use the std::back_inserter without defining the const_reference type? I usually thought that one has to implement the full set of typedefs (value_type, reference, const_reference etc) in order to be compatible with the STL-algorithms library? Or can I safely assume that if my code compiles in this case I am not invoking anything dangerous (e.g. move semantics, which would destroy my other datastructure).


Solution

  • The standard (1998) says that std::back_insert_iterator needs Container::const_reference. In "24.4.2.1 Template class back_insert_iterator", [lib.back.insert.iterator], it says:

    back_insert_iterator<Container>&
    operator=(typename Container::const_reference value);
    

    The 2011 standard only wants Container::value_type,

    back_insert_iterator<Container>&
    operator=(const typename Container::value_type& value);
    back_insert_iterator<Container>&
    operator=(typename Container::value_type&& value);
    

    So, to be compatible with both versions of the C++ standard, define both value_type and const_reference_type.

    In both GCC 4.4.6 and 4.5.1, the definition of operator= is identical (libstdc++-v3/include/bits/stl_iterator.h):

      back_insert_iterator&
      operator=(typename _Container::const_reference __value)
      {
        container->push_back(__value);
        return *this;
      }
    

    and I get the same error with both compilers, perhaps you'll need to double check if you're using the correct compiler versions.