为什么 std::swap<std::array<int,3>> 无法编译?

问题描述 投票:0回答:2

我想交换两个固定大小的整数数组。

与直觉相反,以下内容无法编译,因为没有找到

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)

我也无法理解。

问: 这是怎么回事?

c++ std swap
2个回答
9
投票

您正在寻找的重载是(来自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>>
。然而,查看实现有时可能会产生误导,我建议首先查阅文档。


3
投票

问题似乎是由 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 要求:类型
T
应为 Cpp17MoveConstructible(表 26)和 Cpp17MoveAssignable(表 28)。

代码适用于 vc++,其中库仅根据标准要求检查

is_move_constructible
is_move_assignable

© www.soinside.com 2019 - 2024. All rights reserved.