如何获得广义交换功能?

How to get a generalized Swap-function?

cppreference 上使用 std::swap 的示例我尝试了以下 SWAP-模板:

#include <algorithm>
#include <iostream>

namespace Ns
{
class A
{
    int id{};
 
    friend void swap(A& lhs, A& rhs)
    {
        std::cout << "swap(" << lhs << ", " << rhs << ")\n";
        std::swap(lhs.id, rhs.id);
    }
 
    friend std::ostream& operator<< (std::ostream& os, A const& a)
    {
        return os << "A::id=" << a.id;
    }
 
public:
    A(int i) : id{i} { }
    A(A const&) = delete;
    A& operator = (A const&) = delete;
};
}

template<typename T> void SWAP(T &l, T &r)
{
    try { std::swap(l, r); }
    catch(...) { swap(l, r); }
}

int main()
{
    std::cout << "\n======================\n";
    int a = 5, b = 3;
    std::cout << "before: " << a << ' ' << b << '\n';
    std::swap(a,b);
    std::cout << "after:  " << a << ' ' << b << '\n';
    std::cout << "\n=========\n";
    Ns::A p{6}, q{9};
    std::cout << "before: " << p << ' ' << q << '\n';
    //  std::swap(p, q);  // error, type requirements are not satisfied
    swap(p, q);  // OK, ADL finds the appropriate friend `swap`
    std::cout << "after: " << p << ' ' << q << '\n';

    std::cout << "\n======================\n";
    std::cout << "before: " << a << ' ' << b << '\n';
    SWAP(a,b);
    std::cout << "after:  " << a << ' ' << b << '\n';
    std::cout << "\n=========\n";
    std::cout << "before: " << p << ' ' << q << '\n';
    SWAP(p, q);
    std::cout << "after: " << p << ' ' << q << '\n';
}

处理命名空间中的 'friend' 交换函数;只需调用一个 SWAP 函数即可处理所有情况。

编译器错误:swap was not declared in this scope

为什么调用 swap() 命名空间在 main 中有效,但在模板中无效?
有没有一种方法可以使用通用的 'SWAP' 函数来处理所有此类情况?

(编辑)

感谢@rici,对模板进行了以下更改:

template<typename T> void SWAP(T &l, T &r)
{
    using namespace std;
    swap(l, r);
}

对于我的问题的第一部分,我仍然会感谢 ELI5:what/how/why 这行得通吗...

有2个问题。

请先阅读'std::swap'here的定义。

您将阅读该类型的要求。

  1. 您在交换函数中使用了异常。删除那个。
  2. 从描述中可以看出你的类型一定是

Type requirements

  • T must meet the requirements of MoveAssignable and MoveConstructible.
  • T2 must meet the requirements of Swappable.

您定义(删除)了构造函数和赋值运算符。这样,编译器就不会为您创建标准的 constructors/assign 运算符。请阅读有关 5 的规则。

您的 class 不再是 MoveAssignableMoveConstructible

简单的把删除的运算符和构造函数去掉

喜欢下面的。然后它会编译。

#include <algorithm>
#include <iostream>

namespace Ns
{
    class A
    {
        int id{};

        friend void swap(A& lhs, A& rhs)
        {
            std::cout << "swap(" << lhs << ", " << rhs << ")\n";
            std::swap(lhs.id, rhs.id);
        }

        friend std::ostream& operator<< (std::ostream& os, A const& a)
        {
            return os << "A::id=" << a.id;
        }

    public:
        A(int i) : id{ i } { }
        //A(A const&) = delete;
        //A& operator = (A const&) = delete;
    };
}

template<typename T> 
void SWAP(T& l, T& r)
{
    std::swap(l, r);
}

int main()
{
    std::cout << "\n======================\n";
    int a = 5, b = 3;
    std::cout << "before: " << a << ' ' << b << '\n';
    std::swap(a, b);
    std::cout << "after:  " << a << ' ' << b << '\n';
    std::cout << "\n=========\n";
    Ns::A p{ 6 }, q{ 9 };
    std::cout << "before: " << p << ' ' << q << '\n';
    //  std::swap(p, q);  // error, type requirements are not satisfied
    swap(p, q);  // OK, ADL finds the appropriate friend `swap`
    std::cout << "after: " << p << ' ' << q << '\n';

    std::cout << "\n======================\n";
    std::cout << "before: " << a << ' ' << b << '\n';
    SWAP(a, b);
    std::cout << "after:  " << a << ' ' << b << '\n';
    std::cout << "\n=========\n";
    std::cout << "before: " << p << ' ' << q << '\n';
    SWAP(p, q);
    std::cout << "after: " << p << ' ' << q << '\n';
}