为代理 类 覆盖 std::swap c++

Override std::swap for Proxy classes c++

我被指派用自定义随机访问迭代器实现 vector<bool> class,将每个 bool 表示为 unsigned int 数组中的一个位。我正在使用代理 class,它有一个指向 unsigned int 的指针和一个 index 变量,说明正在修改哪个位。

所以我的 vector<bool>s operator[] 看起来像:

BoolVectorProxy operator[](std::size_t index) {
    validate_bounds(index);
    return BoolVectorProxy(&array[index / BLOCK_CAPACITY], index % BLOCK_CAPACITY);
}

到目前为止一切顺利 - 然而当我们需要时会发生什么,在迭代器上(也 returns BoolVectorProxy 在括号运算符和解引用运算符上),做一些交换?

此代码无法编译:

Vector<bool> a({true, false});
std::swap(a[0], a[1]);
std::cout << a[0] << " " << a[1] << std::endl;

它应该打印 0 1 显然但是不太愉快的错误消息说我无法从 rvalue 初始化类型 BoolVectorProxy& 的非常量引用输入 BoolVectorProxy。该错误是可以理解的 - 它尝试使用默认值 std::swap 但无法将我返回的 rvalue 转换为引用。

如何解决这个问题?

问题是 std::swap 声明为:

template< class T >
void swap( T& a, T& b );

对于不是 MSVC 的编译器,您不能将右值传递给它,而 a[0] 是右值(a[1] 也是)。您也不能为 BoolVectorProxy 提供自己的 std::swap 专业化,因为那个 still 必须采用左值引用。

唯一的解决方案是在关联的命名空间中编写您自己的 swap,以便可以通过参数相关查找找到它:

namespace N  // or whatever
{
    struct BoolVectorProxy { ... };

    // take proxies by value
    void swap(BoolVectorProxy a, BoolVectorProxy b)
    {
        // something like this
        bool tmp = static_cast<bool>(a);
        a = static_cast<bool>(b);
        b = tmp;
    }
}

不合格调用swap:

Vector<bool> a({true, false});
using std::swap;
swap(a[0], a[1]);

这是一个非常普遍的需求,将其包装在:

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

你可以用它来写:

Vector<bool> a({true, false});
adl_swap(a[0], a[1]);