如何获得广义互换功能?

发布于 2025-01-23 20:26:19 字数 2379 浏览 0 评论 0原文

使用std ::交换的示例 cppreference 我尝试了以下交换 -template:

#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';
}

处理名称空间中的“朋友”交换函数;只需一个单个交换函数即可处理所有情况。

compiler-error:在此范围中未声明

为什么在main中调用swap()在模板中工作。 ?
是否有一种方法可以使用广义的“交换”功能来处理所有此类情况?

(编辑)

感谢@rici对模板的以下更改的作用:

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

对于我的问题的第一部分,我仍然感谢ELI5:什么/为什么/为什么工作...

Using the example for std::swap on cppreference I tried the following SWAP-template:

#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';
}

to handle the 'friend' swap-function in the namespace; to have just a single SWAP function to call that will handle all cases.

The compiler-error: swap was not declared in this scope

Why does calling swap() for the namespace work in main but not in the template?
and is there a way to have a generalized 'SWAP'-function to handle all such cases?

(edit)

Thanks to @rici the following change to the template works:

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

I would still appreciate an ELI5 for the first part of my question: what/how/why does this work ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

诗笺 2025-01-30 20:26:19

有两个问题。

请首先阅读'std ::交换'的定义'在这里

您将阅读该类型的要求。

  1. 您正在使用交换功能中的异常。删除。
  2. 从描述中,您可以看到您的类型必须是

类型要求

  • t必须满足可移动和可移动的要求。
  • t2必须满足可交换的要求。

您定义了(删除)构造函数和分配操作员。这样,编译器将不会为您创建标准的构造函数/分配运算符。请阅读有关5规则的信息。

您的班级不再是 moveAssignable moveconstructiblesible

只需删除已删除的操作员和构造函数即可。

像下面一样。然后它将编译。

#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';
}

There are 2 problems.

Please first read the definition of 'std::swap' here.

You will read the requirements for the type.

  1. You are using exceptions in your swap function. Remove that.
  2. From the description, you can see that your type must be

Type requirements

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

You defined (deleted) a constructor and assign operator. With that the compiler will not create the standard constructors/assign operators for you. Please read about the rule of 5.

Your class is no longer MoveAssignable and MoveConstructible.

Simply remove the deleted operator and constructor.

Like the below. Then it will compile.

#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';
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文