fork download
  1. // privateメンバへのアクセス サンプル
  2.  
  3. // 元となるコード
  4. // https://g...content-available-to-author-only...b.com/1528856
  5. // Accessing Private Data
  6. // c.f. http://b...content-available-to-author-only...t.com/2010/07/access-to-private-members-thats-easy.html
  7.  
  8. #include <iostream>
  9.  
  10. // ----------------------------------------------------------
  11. // Accessor
  12. // Tag には、後述のA_mem1やA_mem2が渡される。
  13. // Tag::type は、アクセスするメンバのメンバポインタ型となる。
  14. template <class Tag>
  15. struct Accessor {
  16. static typename Tag::type value;
  17. };
  18.  
  19. // staticメンバの実体
  20. // アクセスしたい型のメンバポインタを保持する。
  21. template <class Tag>
  22. typename Tag::type Accessor<Tag>::value;
  23.  
  24. // ----------------------------------------------------------
  25. // Initializer
  26. template <class Tag, typename Tag::type p>
  27. struct Initializer {
  28. // コンストラクタにおいて
  29. // Accessor型のstaticメンバ value に p (メンバポインタ)
  30. // を設定する。
  31. Initializer() { Accessor<Tag>::value = p; }
  32. static Initializer instance;
  33. };
  34.  
  35. // 初期化を駆動するための static オブジェクト(自身)の定義
  36. // explicit instantiation によって、int main() 前に
  37. // 生成されることが確定し、生成の際、コンストラクタが
  38. // 呼び出されることになる。
  39. template <class Tag, typename Tag::type p>
  40. Initializer<Tag, p> Initializer<Tag, p>::instance;
  41.  
  42. // ------------------------------------------------------
  43. // Target Class
  44. // privateメンバにアクセスされるクラス
  45. struct A {
  46. A(int mem1, int mem2):mem1(mem1), mem2(mem2) {}
  47. void print() const {
  48. std::cout << "mem1 = " << mem1 << " mem2 = " << mem2 << std::endl;
  49. }
  50. private:
  51. int mem1;
  52. int mem2;
  53. static int smem; // static
  54. };
  55. int A::smem = 42; // static
  56.  
  57. // Tagクラス。アクセスするメンバの、メンバポインタ型を
  58. // をタイプメンバ type として持つ
  59. struct A_mem1 { typedef int A::* type; };
  60. struct A_mem2 { typedef int A::* type; };
  61. struct A_smem { typedef int* type; }; // static
  62.  
  63.  
  64. // ------------------------------------------------------
  65. // Template の Explicit instantiation
  66. // ここでは private メンバにアクセスできる
  67. // A::memのアドレスで、Initialize経由でAccessor::valueを
  68. // 設定
  69.  
  70. // 14.7.2/12 The usual access checking rules do not apply
  71. // to names used to specify explicit instantiations.
  72. // [ Note: In particular, the template arguments and
  73. // names used in the function declarator (including
  74. // parameter types,return types and exception
  75. // specifications) may be private types or objects
  76. // which would normally not be accessible and the
  77. // template may be a member template or member function
  78. // which would not normally be accessible. —end note ]
  79.  
  80. template struct Initializer<A_mem1, &A::mem1>;
  81. template struct Initializer<A_mem2, &A::mem2>;
  82. template struct Initializer<A_smem, &A::smem>; // static
  83.  
  84. int main() {
  85. A a(1, 2);
  86. // Accessorを経由して (設定済みの )mem にアクセス
  87. std::cout << *Accessor<A_smem>::value << std::endl; // static
  88. std::cout << a.*Accessor<A_mem1>::value << std::endl;
  89. std::cout << a.*Accessor<A_mem2>::value << std::endl;
  90. a.*Accessor<A_mem1>::value = 3;
  91. a.*Accessor<A_mem2>::value = 4;
  92. a.print();
  93. // ちなみに、Explicit instantiation 以外の箇所では
  94. // private メンバにアクセスできない
  95. // Initializer<A, &A::mem>(); // error A::mem is private
  96. }
  97. // Output:
  98. /*
  99. 42
  100. 1
  101. 2
  102. mem1 = 3 mem2 = 4
  103. */
  104.  
Success #stdin #stdout 0.02s 2724KB
stdin
Standard input is empty
stdout
42
1
2
mem1 = 3 mem2 = 4