【问题标题】:2 dimensional bitset and square bracket operator [duplicate]二维位集和方括号运算符[重复]
【发布时间】:2021-04-16 21:55:32
【问题描述】:

对于个人项目,我需要使用 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) 移动到受保护的位置。

我不知道作者在说什么?如何实现这个代理对象?如有任何帮助,我将不胜感激。

【问题讨论】:

  • 由于您不能返回指向单个位的指针或引用,因此您必须返回一个指向该位所在字节的对象以及一个告诉 which 它“指向”的位。您还需要实现运算符以使其 act 就像它是“真实的东西”。为了便于实现这一点并提高性能,我建议 operator()(size_t, size_t) 就像帖子的作者所做的那样。
  • C++ 中没有operator[][]。如果你想在Matrix 中实现这样的行为,你需要实现operator[],它返回一些其他类(比如RowColumn),它也重载了operator[]。这个Row 是一个代理。
  • 我的建议是注意[i][j] 符号上的轻蔑程度以及它导致的额外工作并避免它。在可能的情况下,坚持使用呼叫接线员并使用(i,j)

标签: c++ std-bitset


【解决方案1】:

如何实现这个代理对象?

您使用自定义语义(通常是重载的运算符)构造代理对象,并从父对象的operator[] 返回它。下面我举一个例子,甚至有两个代理对象——首先operator[]返回一个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";
}

【讨论】:

    【解决方案2】:

    想象一个类 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);
    }
    

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

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

    【讨论】:

      猜你喜欢
      • 2017-08-15
      • 1970-01-01
      • 2012-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-25
      • 2016-01-17
      相关资源
      最近更新 更多