我想交换两个固定大小的整数数组。
与直觉相反,以下内容无法编译,因为没有找到
swap
的匹配实例。
#include <array>
#include <utility>
int main()
{
std::array<int,3> a, b;
std::swap< std::array<int,3> >( a, b );
return 0;
}
我觉得这很令人惊讶。但是,用
std::swap(a,b)
替换交换可以编译并且(根据 VSCode)具有签名
inline void std::swap<int, 3UL>(std::array<int, 3UL> &__one, std::array<int, 3UL> &__two)
我也无法理解。
问: 这是怎么回事?
您正在寻找的重载是(来自cppreference):
template< class T, std::size_t N > constexpr void swap( std::array<T, N>& lhs, std::array<T, N>& rhs ) noexcept(/* see below */);
如错误报告所示,不存在与
swap
匹配的可行的 std::swap<std::array<int,3>>
重载。
这将是显式提供模板参数的“正确”方式:
#include <array>
#include <utility>
int main()
{
std::array<int,3> a, b;
std::swap<int,3>( a, b );
return 0;
}
我怀疑在某种情况下你真的想这样做。
PS:您还可以在从 VSCOde 获得的签名中看到:
std::swap<int, 3UL>
不是 std::swap<std::array<int,3UL>>
。然而,查看实现有时可能会产生误导,我建议首先查阅文档。
问题似乎是由 libstdc++ 实现引起的。它对
tuple-like
的适当“基本”变体中使用的类型强制执行 std::swap
要求
(来源):
template<typename _Tp>
_GLIBCXX20_CONSTEXPR
inline
#if __cplusplus >= 201103L
typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
is_move_constructible<_Tp>,
is_move_assignable<_Tp>>::value>::type
#else
void
#endif
swap(_Tp& __a, _Tp& __b)
即使标准没有提到这样的限制:
20.2.2
交换 [实用程序.swap]
template<class T>
constexpr void swap(T& a, T& b) noexcept(see below );
1 备注:此函数是指定的定制点 (16.5.4.2.1),不得参与重载决策,除非是is_move_constructible_v<T>
并且true
是is_move_assignable_v<T>
。true
内的表达式相当于:noexcept
is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>
2 要求:类型应为 Cpp17MoveConstructible(表 26)和 Cpp17MoveAssignable(表 28)。T
代码适用于 vc++,其中库仅根据标准要求检查
is_move_constructible
和 is_move_assignable
。