私はC++で書かれた静的ライブラリを持っています。静的ライブラリで定義されているクラスのヘッダーファイルもあります。
静的ライブラリで定義されたクラスのプライベートメンバーにアクセスして、クラス宣言にフレンド関数を導入できますか?
私はC++で書かれた静的ライブラリを持っています。静的ライブラリで定義されているクラスのヘッダーファイルもあります。
静的ライブラリで定義されたクラスのプライベートメンバーにアクセスして、クラス宣言にフレンド関数を導入できますか?
ライブラリに同梱されているヘッダーを変更したいということですか? friend
そこに宣言を追加しても機能することは保証されていません。コンパイラが問題ないと言っている場合でも、リンク部分を台無しにする可能性があります。
また、それらのメンバーがprivate
の場合は、アクセスできません。
異なる変換単位で同じエンティティ (ここではクラス) を定義するために異なるトークンのシーケンスを使用することは、技術的に未定義の動作です。
使用するテクニックが何であれ、それを構成するトークンのシーケンスを変更する限り、それはスタンダードの観点からは悪いことです (ただし、実際には機能する可能性があります)。
ヨハネスは、標準を尊重しながらそうする方法を発見しました。a
これは、 class のプライベート属性であるにも関わらずA
、&A::a
書き込めないコンテキストで書き込めるという事実に基づいていますA.a
(おそらく標準の見落とし?)。
コアメソッド:
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
// use
struct A {
A(int a):a(a) { }
private:
int a;
};
// tag used to access A::a
struct A_f {
typedef int A::*type;
friend type get(A_f);
};
template struct Rob<A_f, &A::a>;
int main() {
A a(42);
std::cout << "proof: " << a.*get(A_f()) << std::endl;
}
簡単にするための拡張:
template<typename Tag, typename Member>
struct TagBase {
typedef Member type;
friend type get(Tag);
};
struct A_f : TagBase<A_f, int A::*> { };
編集:
このトリックは (面白いことに)標準で明示的に許可されています。
§14.7.2/12通常のアクセス チェック規則は、明示的なインスタンス化を指定するために使用される名前には適用されません。[...]