Clang:在 libc++ 中使用 std::Map 时复制赋值运算符被删除
Clang: Copy assignment operator is getting deleted while using std::Map in 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
根据错误,在我看来 b/w 移动和复制赋值运算符存在冲突,因此复制赋值被标记为已删除。 limit.cpp class 下定义的 class 对会发生这种情况。我还查看了 libc++ 下的 Pair class 定义,我可以看到复制和移动赋值运算符是明确定义的,所以我想知道为什么会这样。我还检查了 gnustl 中 Pair class 的定义,我看不出有任何我怀疑的显着差异。
移动和复制赋值运算符定义:-
_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
此致,
布佩什
Clang 编译器对映射 class 的 libc++ 有限制。
复制构造函数可能被删除,因为键类型是 const。如果键类型是 const,则不能在复制构造函数期间对其进行分配。不过不确定为什么错误消息指的是移动构造函数。
技术上:-
_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,因此未实例化对 copy operator=。这是 Clang 的特定行为。
我在构建 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
根据错误,在我看来 b/w 移动和复制赋值运算符存在冲突,因此复制赋值被标记为已删除。 limit.cpp class 下定义的 class 对会发生这种情况。我还查看了 libc++ 下的 Pair class 定义,我可以看到复制和移动赋值运算符是明确定义的,所以我想知道为什么会这样。我还检查了 gnustl 中 Pair class 的定义,我看不出有任何我怀疑的显着差异。
移动和复制赋值运算符定义:-
_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
此致,
布佩什
Clang 编译器对映射 class 的 libc++ 有限制。 复制构造函数可能被删除,因为键类型是 const。如果键类型是 const,则不能在复制构造函数期间对其进行分配。不过不确定为什么错误消息指的是移动构造函数。
技术上:-
_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,因此未实例化对 copy operator=。这是 Clang 的特定行为。