问题
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