C++ 中, 私用成員是不允許直接訪問的, 例如下列程式碼就會產生編碼錯誤 :

#include <iostream>

using namespace std;
struct s {
private:
    int data {100};
};
int main() {
    s p;
    cout << p.data << endl;     //Error : 'data' is a private member of 's'
}

但是最近有人發現, 可以通過樣板來竊取私用成員. C++ 標準中有一條規定, 在樣板明確具現化的過程中, 不考慮訪問限制. 也就是說, 當我手動具現化某個樣板的時候, 就可以不考慮類別中的訪問限制. 那麼有些人就想出了如下的虛擬碼 :

template <T *Class::MemPtr>
struct stealer;
template struct stealer<&class_name::class_member>;

在上述過程中, 由於編碼器不會考慮類別 Class 中的訪問限制, 因此上述程式碼可以直接竊取到私用成員. 於是, 我們想到 :

#include <iostream>

using namespace std;
struct s {
private:
    int data {100};
};
template <int s::*data>
struct stealer {
    void steal(const s *p) noexcept {
        cout << p->*data << endl;
    }
};
int main() {
    s p;
    //cout << p.data << endl;     //Error : 'data' is a private member of 's'
    stealer<&s::data> {}.steal(&p);
}

但是, 上述程式碼同樣不可行. 因為 stealer<&s::data> steal(&p); 並不是手動具現化. 因此, 我們並不能宣告 stealer 的具現體. 但是如果不宣告 stealer 的具現體, 應該如何直接呼叫成員函式 steal 呢? 我們想到使用友誼函式 :

#include <iostream>

using namespace std;
struct s {
private:
    int data {100};
};
void steal(const s *) noexcept;
template <int s::*data>
struct stealer {
    friend void steal(const s *p) noexcept {
        cout << p->*data << endl;
    }
};
template struct stealer<&s::data>;
int main() {
    s p;
    //cout << p.data << endl;     //Error : 'data' is a private member of 's'
    steal(&p);      //輸出 : 100
}

這樣, 我們就竊取到了類別 s 的私用成員 data. 除了成員變數之外, 成員函式同樣可行 :

#include <iostream>

using namespace std;
struct s {
private:
    int data {100};
    void print() {
        cout << 1 << endl;
    }
public:
    void set(int data) noexcept {
        this->data = data;
    }
};
void steal(const s *) noexcept;
template <int s::*data>
struct stealer {
    friend void steal(const s *p) noexcept {
        cout << p->*data << endl;
    }
};
template struct stealer<&s::data>;
void steal(s &p) noexcept;
template <void (s::*memfun)()>
struct memfun_stealer {
    friend void steal(s &p) noexcept {
        (p.*memfun)();
    }
};
template struct memfun_stealer<&s::print>;
int main() {
    s p;
    //cout << p.data << endl;     //Error : 'data' is a private member of 's'
    steal(&p);      //輸出 : 100
    p.set(200);
    steal(&p);      //輸出 : 200
    steal(p);       //輸出 : 1
}

樣板配合友誼函式貌似是 C++ Bug 頻出的地方, 上有 Stateful Meta-Programming, 下有竊取私用成員. 不過準確地來說, 這確確實實是 C++ 標準有失誤的地方, 不能說是一個 C++ 標準的錯誤. 但是 Stateful Meta-Programming 確確實實是一個 C++ 標準的錯誤, 它已經被 C++ 標準委員會欽定為 ill-formed. 如果有需要, 它可能在 C++ 23 或者 C++ 26 中被修復

最後, 我是真佩服發現這個特性的人的洞察力...