根据非成员 swap() 实现成员 swap()
Implementing member swap() in terms of non-member swap()
我正在实现一个具有与 std::array
类似界面的 class,它同时具有 member swap()
and the non-member swap()
.
因为我想让我的 class 模仿标准容器,所以我想实现两种 swap()
(非成员 swap()
是通过 ADL 实现的,因为专门std::swap()
是不允许的):
class A {
public:
friend void swap(A& a, A& b) { /* swap the stuff */ }
void swap(A& other) { swap(*this, other); }
};
但是,我似乎无法从 class 内部调用非成员 swap()
,因为它更喜欢成员 swap()
,即使它只有一个范围。将其更改为 ::swap(*this, other)
也不起作用,因为 in-class 友元函数只能通过 ADL 找到。我如何从 class 中调用非成员 swap()
?
以下对我有效(打印两次 blah)
#include <utility>
#include <iostream>
class A {
public:
friend void swap(A& a, A& b) { std::cout << "blah\n";/* swap the stuff */ }
void swap(A& other) { using std::swap; swap(*this, other); }
};
int main() {
A a, b;
swap(a,b);
a.swap(b);
}
问题在于成员函数 swap
的名称在 A::swap
的主体中隐藏了名称空间作用域 swap
。 A::swap
中 swap
的非限定名称查找永远不会找到命名空间范围 swap
,因此,命名空间范围 swap
不会成为重载集的一部分。解决这个问题的一种方法是简单地在 A::swap
:
的正文中添加名称空间范围 swap
的声明
class A
{
public:
friend void swap(A& a, A& b) { /* swap the stuff */ }
void swap(A& other)
{
void swap(A& a, A& b);
swap(*this, other);
}
};
话虽这么说,但我不确定这对您到底有什么用。显而易见的解决方案是根据 A::swap
而不是相反的方式来实现命名空间范围 swap
。就个人而言,我一开始就不会使用 swap
成员函数。 The typical way of swapping a
和 b
只是 swap(a, b)
…
您可以先声明 class 和交换函数,然后在成员函数中使用全局命名空间说明符。
现在您可以在 class 之外自由定义交换函数了。
#include <algorithm>
#include <iostream>
class A;
void swap(A& a, A& b);
class A {
int the_stuff;
public:
A(int a): the_stuff(a) {}
friend void swap(A& a, A& b);
void print_stuff(){std::cout << "A's stuff is " << the_stuff << std::endl;}
void swap(A& other){
::swap(*this, other);
std::cout << "Member swap" << std::endl;}
};
void swap(A& a, A& b)
{
std::swap(a.the_stuff, b.the_stuff);
std::cout << "Friend swap" << std::endl;
}
int main()
{
A a = 1, b = 2;
a.print_stuff();
swap(a, b);
a.print_stuff();
return 0;
}
输出:
//> A's stuff is 1
//> Friend swap
//> A's stuff is 2
我正在实现一个具有与 std::array
类似界面的 class,它同时具有 member swap()
and the non-member swap()
.
因为我想让我的 class 模仿标准容器,所以我想实现两种 swap()
(非成员 swap()
是通过 ADL 实现的,因为专门std::swap()
是不允许的):
class A {
public:
friend void swap(A& a, A& b) { /* swap the stuff */ }
void swap(A& other) { swap(*this, other); }
};
但是,我似乎无法从 class 内部调用非成员 swap()
,因为它更喜欢成员 swap()
,即使它只有一个范围。将其更改为 ::swap(*this, other)
也不起作用,因为 in-class 友元函数只能通过 ADL 找到。我如何从 class 中调用非成员 swap()
?
以下对我有效(打印两次 blah)
#include <utility>
#include <iostream>
class A {
public:
friend void swap(A& a, A& b) { std::cout << "blah\n";/* swap the stuff */ }
void swap(A& other) { using std::swap; swap(*this, other); }
};
int main() {
A a, b;
swap(a,b);
a.swap(b);
}
问题在于成员函数 swap
的名称在 A::swap
的主体中隐藏了名称空间作用域 swap
。 A::swap
中 swap
的非限定名称查找永远不会找到命名空间范围 swap
,因此,命名空间范围 swap
不会成为重载集的一部分。解决这个问题的一种方法是简单地在 A::swap
:
swap
的声明
class A
{
public:
friend void swap(A& a, A& b) { /* swap the stuff */ }
void swap(A& other)
{
void swap(A& a, A& b);
swap(*this, other);
}
};
话虽这么说,但我不确定这对您到底有什么用。显而易见的解决方案是根据 A::swap
而不是相反的方式来实现命名空间范围 swap
。就个人而言,我一开始就不会使用 swap
成员函数。 The typical way of swapping a
和 b
只是 swap(a, b)
…
您可以先声明 class 和交换函数,然后在成员函数中使用全局命名空间说明符。
现在您可以在 class 之外自由定义交换函数了。
#include <algorithm>
#include <iostream>
class A;
void swap(A& a, A& b);
class A {
int the_stuff;
public:
A(int a): the_stuff(a) {}
friend void swap(A& a, A& b);
void print_stuff(){std::cout << "A's stuff is " << the_stuff << std::endl;}
void swap(A& other){
::swap(*this, other);
std::cout << "Member swap" << std::endl;}
};
void swap(A& a, A& b)
{
std::swap(a.the_stuff, b.the_stuff);
std::cout << "Friend swap" << std::endl;
}
int main()
{
A a = 1, b = 2;
a.print_stuff();
swap(a, b);
a.print_stuff();
return 0;
}
输出:
//> A's stuff is 1
//> Friend swap
//> A's stuff is 2