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. };
  54.  
  55. // Tagクラス。アクセスするメンバの、メンバポインタ型を
  56. // をタイプメンバ type として持つ
  57. struct A_mem1 { typedef int A::* type; };
  58. struct A_mem2 { typedef int A::* type; };
  59.  
  60.  
  61. // ------------------------------------------------------
  62. // Template の Explicit instantiation
  63. // ここでは private メンバにアクセスできる
  64. // A::memのアドレスで、Initialize経由でAccessor::valueを
  65. // 設定
  66.  
  67. // 14.7.2/12 The usual access checking rules do not apply
  68. // to names used to specify explicit instantiations.
  69. // [ Note: In particular, the template arguments and
  70. // names used in the function declarator (including
  71. // parameter types,return types and exception
  72. // specifications) may be private types or objects
  73. // which would normally not be accessible and the
  74. // template may be a member template or member function
  75. // which would not normally be accessible. —end note ]
  76.  
  77. template struct Initializer<A_mem1, &A::mem1>;
  78. template struct Initializer<A_mem2, &A::mem2>;
  79.  
  80. int main() {
  81. A a(1, 2);
  82. // Accessorを経由して (設定済みの )mem にアクセス
  83. std::cout << a.*Accessor<A_mem1>::value << std::endl;
  84. std::cout << a.*Accessor<A_mem2>::value << std::endl;
  85. a.*Accessor<A_mem1>::value = 3;
  86. a.*Accessor<A_mem2>::value = 4;
  87. a.print();
  88. // ちなみに、Explicit instantiation 以外の箇所では
  89. // private メンバにアクセスできない
  90. // Initializer<A, &A::mem>(); // error A::mem is private
  91. }
  92. // Output:
  93. /*
  94. 1
  95. 2
  96. mem1 = 3 mem2 = 4
  97. */
  98.  
Success #stdin #stdout 0.02s 2724KB
stdin
Standard input is empty
stdout
1
2
mem1 = 3 mem2 = 4