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

我只是一个虾纸丫 提交于 2019-12-23 11:46:41

问题


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).


回答1:


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.




回答2:


The reason that you need const_reference defined for your data-structure is because the assignment operator in GCC 4.4 for an lvalue argument type in the std::back_insert_iterator class is defined as:

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

Thus const_reference needs to be a resolvable identifier in your class-type in to properly instantiate the assignment operator in the std::back_insert_iterator class template.

In GCC 4.5, this definition of the assignment operator for lvalue arguments has been changed to

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

in order to support the new C++11 specification. Since your code compiles correctly with GCC 4.5, I'm assuming you must have value_type properly defined for your data-structure.



来源:https://stackoverflow.com/questions/8081072/stdback-inserter-needs-const-reference-on-older-gcc-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!