📜 ⬆️ ⬇️

C ++ and reflection on the knee

It took recently to be able to access the field in the structure by its name - write, read the value. And so that the performance of those places where it is not used has not changed.
Here's what happened:
Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );
  1. Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );
  2. Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );
  3. Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );
  4. Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );
  5. Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );
  6. Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );
  7. Copy Source | Copy HTML TUser user; user.StoreValue(); double SalaryRef; user.SetField( "Salary" , SalaryRef); // user.GetField( "Salary" , SalaryRef); // - // , - double Salary = user.GetField< double >( "Salary" );


The whole secret in the "magic bubbles" - in the class from which TUser is inherited, and one function - StoreValue ().
Details under the cut.

Important: This solution is cross-platform, it requires only STL and the C ++ compiler, which “can” templates.
')

At the beginning - the synonyms of types - in order to make it easier to change in the case of experiments.

Copy Source | Copy HTML
  1. typedef std :: string TWString;
  2. typedef __int64 bigint;
  3. const double DBL_NULL = 0 ;
  4. const bigint INT_NULL = - 1 ;
  5. const TWString STR_NULL = TWString ();


The base class, which provides "goodies"
Copy Source | Copy HTML
  1. struct BaseType
  2. {
  3. bool isstored;
  4. enum BaseValueState {bvsStore, bvsSet, bvsGet, bvsErase};
  5. BaseType (): IsStored ( false )
  6. {
  7. }
  8. virtual ~ BaseType ()
  9. {
  10. if (IsStored)
  11. {
  12. int tempInt = int ();
  13. double tempDbl = double ();
  14. TWString tempStr = TWString ();
  15. FieldStorage ( "" , tempInt, bvsErase);
  16. FieldStorage ( "" , tempStr, bvsErase);
  17. FieldStorage ( "" , tempDbl, bvsErase);
  18. }
  19. }
  20. virtual void StoreValue () = 0 ;
  21. template < class T >
  22. void FieldStorage ( const TWString & Tag, T & Value,
  23. BaseValueState State = bvsStore)
  24. {
  25. typedef std :: map < void *, std :: map < TWString , T *>> FieldMap;
  26. static FieldMap Values;
  27. static T Empty = T ();
  28. if (! IsStored)
  29. IsStored = true ;
  30. switch (State)
  31. {
  32. case bvsStore:
  33. Values ​​[ this ] [Tag] = & Value;
  34. break ;
  35. case bvsSet:
  36. {
  37. T * Ptr = Values ​​[ this ] [Tag];
  38. if (Ptr)
  39. * Ptr = Value;
  40. }
  41. break ;
  42. case bvsGet:
  43. {
  44. T * Ptr = Values ​​[ this ] [Tag];
  45. Value = (Ptr)? * Ptr: Empty;
  46. }
  47. break ;
  48. case bvsErase:
  49. Values.erase ( this );
  50. break ;
  51. }
  52. }
  53. template <typename T >
  54. void GetField ( const TWString & Tag, T & Value)
  55. {
  56. FieldStorage (Tag, Value, bvsGet);
  57. }
  58. template <typename T >
  59. void SetField ( const TWString & Tag, T & Value)
  60. {
  61. FieldStorage (Tag, Value, bvsSet);
  62. }
  63. template <typename T >
  64. T GetField ( const TWString & Tag)
  65. {
  66. T Value;
  67. FieldStorage (Tag, Value, bvsGet);
  68. return Value;
  69. }
  70. };


And here we are inherited from it:
Copy Source | Copy HTML
  1. struct TUser : public BaseType
  2. {
  3. TUser ( int AId = INT_NULL, const TWString & ALogin = STR_NULL, const double ASalary = DBL_NULL)
  4. : Id (AId), Login (ALogin), Salary (ASalary)
  5. {}
  6. bigint Id;
  7. TWString Login;
  8. double Salary;
  9. void StoreValue ()
  10. {
  11. FieldStorage ( "Id" , Id);
  12. FieldStorage ( "Login" , Login);
  13. FieldStorage ( "Salary" , Salary);
  14. }
  15. };

Source: https://habr.com/ru/post/83521/


All Articles