如何实现这个代理对象?
您使用自定义语义(通常是重载的运算符)构造代理对象并从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";
}