C++11 对set集合使用transform和negate方法编译报错

环境:C++11 ;Apple clang version 12.0.0 (clang-1200.0.32.29)

代码:

#include <algorithm>
#include <set>
#include <functional>

using namespace std;

int main(int argc, char const* argv[]) {
    set<int> collSet{2,3,1,0,5};
    transform(collSet.begin(), collSet.end(), collSet.begin(), negate<int>());
    return 0;
}

错误提示:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:1948:19: error: cannot assign to return value because function 'operator*' returns a const value
        *__result = __op(*__first);
        ~~~~~~~~~ ^
transformset.cpp:9:5: note: in instantiation of function template specialization 'std::__1::transform<std::__1::__tree_const_iterator<int, std::__1::__tree_node<int, void *> *, long>, std::__1::__tree_const_iterator<int, std::__1::__tree_node<int, void
      *> *, long>, std::__1::negate<int> >' requested here
    transform(collSet.begin(), collSet.end(), collSet.begin(), negate<int>());
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tree:921:31: note: function 'operator*' which returns const-qualified type 'std::__1::__tree_const_iterator<int, std::__1::__tree_node<int, void
      *> *, long>::reference' (aka 'const int &') declared here
    _LIBCPP_INLINE_VISIBILITY reference operator*() const

在书上和网上看到很多这样的写法,但是本地运行报错,求大佬指点迷津。

我看了下源码,返回的iterator不是const的

//Set源码
 _LIBCPP_INLINE_VISIBILITY
          iterator begin() _NOEXCEPT       {return __tree_.begin();}
    _LIBCPP_INLINE_VISIBILITY
    const_iterator begin() const _NOEXCEPT {return __tree_.begin();}
    _LIBCPP_INLINE_VISIBILITY
          iterator end() _NOEXCEPT         {return __tree_.end();}
    _LIBCPP_INLINE_VISIBILITY
    const_iterator end()   const _NOEXCEPT {return __tree_.end();}

问题在于,transform中会调用*first

template <class _InputIterator, class _OutputIterator, class _UnaryOperation>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
_OutputIterator
transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op)
{
    for (; __first != __last; ++__first, (void) ++__result)
        *__result = __op(*__first);//这里这里
    return __result;
}

而在_tree中,*操作符重载有const限制,如下:


_LIBCPP_INLINE_VISIBILITY reference operator*() const // 这里这里
    {return __get_np()->__value_;}
_LIBCPP_INLINE_VISIBILITY pointer operator->() const
    {return pointer_traits<pointer>::pointer_to(__get_np()->__value_);}

应该是这个原因。

其实我比较纳闷,网上那些人是怎么通过编译的,可能是C++版本不一样?我用的11(狗头)