叮当声:在libc ++中使用std :: Map时,副本分配运算符将被删除

时间:2018-10-04 05:54:13

标签: android c++ stl clang libc++

在构建PROJ_XXX时遇到一些构建错误。我正在做出从gnustl lib迁移到libc ++的更改。

构建错误

f:\office\build\droidx86\debug\proj_xxxx\test\android\objd\droidx86\clang-temp\EventPerfTrackerTests.cpp
Exit code: 0
Running: f:\androidndk.16.1.1\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe @f:\office\build\droidx86\debug\proj_xxxx\test\android\objd\droidx86\android_clang_cpp_flags.rsp -c f:\office\dev\proj_xxxx\test\android\..\EventPerfTrackerTests.cpp -o f:\office\build\droidx86\debug\proj_xxxx\test\android\objd\droidx86\clang-temp\EventPerfTrackerTests.cpp\compile.tmp
In file included from f:\office\dev\proj_xxxx\test\android\..\EventPerfTrackerTests.cpp:1:
In file included from F:/Office/dev/liblet/precomp/android\precomp.h:1:
In file included from F:/Office/Import/droidx86/debug/proj_xxxx/x-none/droidx86/inc\sharedPch/sharedPch_android.h:9:
In file included from F:/Office\Import\droidx86\debug\proj_xxxx\x-none\droidx86\inc\sharedPch\sharedPch.h:39:
In file included from F:/Office\Import\droidx86\debug\proj_xxxx\x-none\droidx86\inc\msoSTL.h:53:
f:/nugetcache\androidndk.16.1.1\sources\cxx-stl\llvm-libc++\include\map(629,15) :  error: object of type 'std::__ndk1::pair<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>' cannot be assigned because its copy assignment operator is implicitly deleted
        {__nc = __v.__cc; return *this;}
              ^
f:/nugetcache\androidndk.16.1.1\sources\cxx-stl\llvm-libc++\include\__tree(1645,35) :  note: in instantiation of member function 'std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>::operator=' requested here
                __cache->__value_ = *__first;
                                  ^
f:/nugetcache\androidndk.16.1.1\sources\cxx-stl\llvm-libc++\include\__tree(1575,9) :  note: in instantiation of function template specialization 'std::__ndk1::__tree<std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>, std::__ndk1::__map_value_compare<const wchar_t *const, std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>, std::__ndk1::less<const wchar_t *const>, true>, std::__ndk1::allocator<std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData> > >::__assign_multi<std::__ndk1::__tree_const_iterator<std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>, std::__ndk1::__tree_node<std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>, void *> *, int> >' requested here
        __assign_multi(__t.begin(), __t.end());
        ^
f:/nugetcache\androidndk.16.1.1\sources\cxx-stl\llvm-libc++\include\map(912,21) :  note: in instantiation of member function 'std::__ndk1::__tree<std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>, std::__ndk1::__map_value_compare<const wchar_t *const, std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>, std::__ndk1::less<const wchar_t *const>, true>, std::__ndk1::allocator<std::__ndk1::__value_type<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData> > >::operator=' requested here
            __tree_ = __m.__tree_;
                    ^
f:\office\dev\proj_xxxx\test\android\..\EventPerfTrackerTests.cpp(50,27) :  note: in instantiation of member function 'std::__ndk1::map<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData, std::__ndk1::less<const wchar_t *const>, std::__ndk1::allocator<std::__ndk1::pair<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData> > >::operator=' requested here
                m_latestSTEDataReceived = dataMap;
                                        ^
f:/nugetcache\androidndk.16.1.1\sources\cxx-stl\llvm-libc++\include\Utility(325,5) :  note: copy assignment operator is implicitly deleted because 'pair<const wchar_t *const, ::proj_xxxx::EventPerfTrackerSTEData>' has a user-declared move constructor
    pair(pair&&) = default;
    ^
1 error generated.
Exit code: 1

基于该错误,在我看来似乎存在黑白移动和复制分配操作符冲突,并且由于该复制分配被标记为已删除。这是在limit.cpp类下定义的Pair类发生的。我还研究了libc ++下的Pair类定义,并且可以看到复制和移动赋值运算符已明确定义,所以我想知道为什么会这样。我还检查了gnustl中Pair类的定义,没有发现我可以怀疑的任何显着差异。

“移动和复制分配”运算符定义:-

_LIBCPP_INLINE_VISIBILITY
    pair& operator=(typename conditional<
                        is_copy_assignable<first_type>::value &&
                        is_copy_assignable<second_type>::value,
                    pair, __nat>::type const& __p)
        _NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value &&
                   is_nothrow_copy_assignable<second_type>::value)
    {
        first = __p.first;
        second = __p.second;
        return *this;
    }

    _LIBCPP_INLINE_VISIBILITY
    pair& operator=(typename conditional<
                        is_move_assignable<first_type>::value &&
                        is_move_assignable<second_type>::value,
                    pair, __nat>::type&& __p)
        _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value &&
                   is_nothrow_move_assignable<second_type>::value)
    {
        first = _VSTD::forward<first_type>(__p.first);
        second = _VSTD::forward<second_type>(__p.second);
        return *this;
    }

失败代码:

const size_t NumDurationBuckets = 7;

struct EventPerfTrackerSTEData
{
       std::uint32_t m_timeSettingInSeconds;
       std::uint32_t m_timeActualInSeconds;
       std::uint32_t m_totalEventsInTimew;
       std::uint32_t m_maxEventDurationSeenInTime;
       std::array<uint32_t, NumDurationBuckets> m_durationBucketsEventCounts;
};
       virtual void SendData(const std::map<const wchar_t * const, EventPerfTrackerSTEData> &dataMap) noexcept override
       {
              ++m_timesSendEventCalled;
              m_latestSTEDataReceived = dataMap;
       }

       std::map<const wchar_t * const, EventPerfTrackerSTEData> m_latestSTEDataReceived;

我还可以在开发环境中使用测试代码来复制构建失败场景。 但是在GCC编译器和IdeOne上都发生了同样的情况。

感谢您的帮助。

NDK版本:-16r 最低SDK版本:21

此致

布达佩斯

1 个答案:

答案 0 :(得分:0)

Clang编译器在libc ++中有一个针对地图类的限制。 复制构造函数可能会被删除,因为键类型是const。如果键类型是const,则不能在复制构造函数期间分配它。不过,不确定为什么错误消息引用了move构造函数。

技术上:-

_LIBCPP_INLINE_VISIBILITY
    pair& operator=(typename conditional<
                        is_copy_assignable<first_type>::value &&
                        is_copy_assignable<second_type>::value,
                    pair, __nat>::type const& __p)
        _NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value &&
                   is_nothrow_copy_assignable<second_type>::value)
    {
        first = __p.first;
        second = __p.second;
        return *this;
    }

is_copy_assignable返回false,因此不会实例化对复制操作符=。这是Clang特有的行为。