0

对于个人项目,我需要使用 2D 位集。进行了大量的谷歌搜索,发现了一个非常棒的帖子,其中包含非常有用的代码,https: //forums.codeguru.com/showthread.php?522711-Need-2-dimensional-Bitarray 。来看看答案monarch_dodra

结尾如果有如下语句

我使用“a(1,1)”而不是“a[1][1]”。长话短说,这是一种更好的方法。如果您必须具有 a[1][1] 语法,那么我建议编写一个返回代理对象的 operator[j],它本身具有一个 operator[i],它只是转发回 (j, i)。然后,如果需要,您可以将 operator()(i, j) 移动到受保护的位置。

看不懂作者在说什么?如何实现这个代理对象?我将不胜感激。

4

2 回答 2

1

想象一个Matrix看起来像这样的类:

template<int rows, int columns, class T>
class Matrix {

    template <int r, class T>
    class Columns{
        T _rows[r];
    public:
        T operator[](int index) {
            return _rows[index];
        }
    };

    Columns<rows, T> _Matrix_Columns[columns];

    public:

    Columns<rows, T> operator[](int index) {
        return _Matrix_Columns[index];
    }
};

一个使用这个矩阵的人是这样的:

int main() {
    Matrix<5, 5, char> M;
    char ch = M[1][1]; 
}

中的代码main()实际上可以写成:

int main() {
    Matrix<5, 5, char> M;
    char ch = M.operator[](1).operator[](1);
}

Matrix operator[]返回代理对象Column,它有它自己的,operator[]它返回我们的char

注意:矩阵用于教育目的,它实际上不起作用。

于 2021-04-16T22:15:10.207 回答
1

如何实现这个代理对象?

您使用自定义语义(通常是重载的运算符)构造代理对象并从operator[]父对象返回它。下面我举一个例子,甚至有两个代理对象——首先operator[]返回 a Bitset::Byte,然后Bitset::Byte::operator[]返回Bitset::Bit。很酷的想法是,Bitset::Bit有特殊operator=的允许“设置”它的值。

#include <iostream>
#include <cstddef>
#include <climits>
#include <array>
#include <cassert>
#include <iomanip>

template<size_t N>
struct Bitset {
    std::array<unsigned char, N> mem{};
    struct Bit {
        unsigned char& byte;
        unsigned mask;
        Bit(unsigned char &byte, unsigned idx) :
            byte(byte), mask(1 << idx) {}
        operator unsigned () {
            return (byte & mask) ? 1 : 0;
        }
        Bit& operator=(unsigned v) {
            if (v) {
                byte |= mask;
            } else {
                byte &= mask;
            }
            return *this;
        }
    };
    struct Byte {
        unsigned char& byte;
        Bit operator[](unsigned idx) {
            return {byte, idx};
        }
        operator unsigned () {
            return byte;
        }
    };
    Byte operator[](unsigned idx) {
        return { mem.at(idx) };
    }
};


int main() {
    Bitset<20> a;
    std::cout << "a[1][3] = " << a[1][3] << "\n";
    // let's set 2nd byte 4th bit
    a[1][3] = 1; // yay!
    std::cout << "a[1] = 0x" << std::hex << std::setw(2) << std::setfill('0') <<  a[1] << "\n";
    std::cout << "a[1][3] = " << a[1][3] << "\n";
}

输出:

a[1][3] = 0
a[1] = 0x08
a[1][3] = 1

a[1][3] = something是伟大而惊人的功能,它清晰而精确。但这比在父对象中提供一个函数要多得多

#include <iostream>
#include <cstddef>
#include <climits>
#include <array>
#include <cassert>
#include <iomanip>

template<size_t N>
struct Bitset {
    std::array<unsigned char, N> mem{};
    unsigned char& operator()(size_t n) {
        return mem.at(n);
    }
    void set(size_t n, size_t idx, unsigned v) {
        if (v) {
            mem.at(n) |= 1 << idx;
        } else {
            mem.at(n) &= 1 << idx;
        }
    }
    unsigned operator()(size_t n, size_t idx) {
        return (mem.at(n) & 1 << idx) ? 1 : 0;
    }
};


int main() {
    Bitset<20> a;
    std::cout << "a[1][3] = " << a(1, 3) << "\n";\
    // let's set 2nd byte 4th bit
    // a(1, 3) = 1; // ugh, not possible
    a.set(1, 3, 1);
    std::cout << "a[1] = 0x" << std::hex << std::setw(2) << std::setfill('0') << (unsigned)a(1) << "\n";
    std::cout << "a[1][3] = " << a(1, 3) << "\n";
}
于 2021-04-16T23:07:56.203 回答