通常实施 std::swap 重载的基本原理

Rationale behind the usual implemention of std::swap overloads

让我们考虑以下最小代码示例:

// Dummy struct
struct S
{
    int a;
    char * b;

    // Ctors, etc...
};

void swap(S & lhs, S & rhs)
{
    using std::swap;

    swap(lhs.a, rhs.a);
    swap(lhs.b, rhs.b);
}

上下文

我知道当我们打算调用一个swap()函数时,正确和推荐的方法是做如下:

// Let's assume we want to swap two S instances.
using std::swap;
swap(s1, s2);

这样,ADL 能够找到合适的重载(如果有的话)(在给定的类型命名空间中定义),否则使用 std::swap

然后我阅读了一些 SO 线程:

使用相同习语的地方(即使是内置或指针类型),但不仅是当我们调用 std::swap()重载而且当我们定义它。

问题

如果成员都是内置类型(或指针类型,可能是指向自定义类型的指针),是否仍然necessary/recommended使用该习语而不是显式调用std::swap()

例如,考虑我提供的小代码示例,由于 S 成员是内置类型,是否 fine (well-formed) 来定义它如下所示:

void swap(S & lhs, S & rhs)
{
    std::swap(lhs.a, rhs.a);
    std::swap(lhs.b, rhs.b);
}

或者是否有我看不到的原因仍然需要使用 using std::swap; 方式?

since S members are built-in types, is it fine (well-formed) to define it as below instead: [std::swap usage]

是的。我的意思是,它起作用是因为 std::swap 只是 "swaps the values a and b" if they are both MoveAssignable and MoveConstructible,内置类型是。

If the members are all built-in types (or pointer types, possibly pointers to custom types), is it still necessary/recommended to use that idiom instead of explicitly calling std::swap() ?

只是为了你 class 的未来:如果有一天它的任何成员被用户定义的类型替换,你可能会忘记修改你的 swap 而错过一个“专门的”它的 ADL 实现,仍然调用通用 std::swap,这可能(理论上)效率低下但仍然可以编译。

其实你不用想也可以一直用boost::swap或者自己实现:

template<typename T> void swap(T& a, T& b) {
    using std::swap;
    swap(a, b);
}