如何获得广义交换功能?
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的定义。
您将阅读该类型的要求。
- 您在交换函数中使用了异常。删除那个。
- 从描述中可以看出你的类型一定是
Type requirements
- T must meet the requirements of MoveAssignable and MoveConstructible.
- T2 must meet the requirements of Swappable.
您定义(删除)了构造函数和赋值运算符。这样,编译器就不会为您创建标准的 constructors/assign 运算符。请阅读有关 5 的规则。
您的 class 不再是 MoveAssignable 和 MoveConstructible。
简单的把删除的运算符和构造函数去掉
喜欢下面的。然后它会编译。
#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';
}
在 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的定义。
您将阅读该类型的要求。
- 您在交换函数中使用了异常。删除那个。
- 从描述中可以看出你的类型一定是
Type requirements
- T must meet the requirements of MoveAssignable and MoveConstructible.
- T2 must meet the requirements of Swappable.
您定义(删除)了构造函数和赋值运算符。这样,编译器就不会为您创建标准的 constructors/assign 运算符。请阅读有关 5 的规则。
您的 class 不再是 MoveAssignable 和 MoveConstructible。
简单的把删除的运算符和构造函数去掉
喜欢下面的。然后它会编译。
#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';
}