<tfoot id='SXuBP'></tfoot>
      <i id='SXuBP'><tr id='SXuBP'><dt id='SXuBP'><q id='SXuBP'><span id='SXuBP'><b id='SXuBP'><form id='SXuBP'><ins id='SXuBP'></ins><ul id='SXuBP'></ul><sub id='SXuBP'></sub></form><legend id='SXuBP'></legend><bdo id='SXuBP'><pre id='SXuBP'><center id='SXuBP'></center></pre></bdo></b><th id='SXuBP'></th></span></q></dt></tr></i><div id='SXuBP'><tfoot id='SXuBP'></tfoot><dl id='SXuBP'><fieldset id='SXuBP'></fieldset></dl></div>
      1. <legend id='SXuBP'><style id='SXuBP'><dir id='SXuBP'><q id='SXuBP'></q></dir></style></legend>
      2. <small id='SXuBP'></small><noframes id='SXuBP'>

          <bdo id='SXuBP'></bdo><ul id='SXuBP'></ul>

        可以使用模板按名称访问结构变量吗?

        时间:2023-05-24
      3. <small id='YQf8P'></small><noframes id='YQf8P'>

          <i id='YQf8P'><tr id='YQf8P'><dt id='YQf8P'><q id='YQf8P'><span id='YQf8P'><b id='YQf8P'><form id='YQf8P'><ins id='YQf8P'></ins><ul id='YQf8P'></ul><sub id='YQf8P'></sub></form><legend id='YQf8P'></legend><bdo id='YQf8P'><pre id='YQf8P'><center id='YQf8P'></center></pre></bdo></b><th id='YQf8P'></th></span></q></dt></tr></i><div id='YQf8P'><tfoot id='YQf8P'></tfoot><dl id='YQf8P'><fieldset id='YQf8P'></fieldset></dl></div>

          <tfoot id='YQf8P'></tfoot>

          • <bdo id='YQf8P'></bdo><ul id='YQf8P'></ul>

              <legend id='YQf8P'><style id='YQf8P'><dir id='YQf8P'><q id='YQf8P'></q></dir></style></legend>
                    <tbody id='YQf8P'></tbody>
                  本文介绍了可以使用模板按名称访问结构变量吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

                  限时送ChatGPT账号..

                  假设我有一个这样的结构:

                  Let's suppose I have a struct like this:

                  struct my_struct
                  {
                    int a;
                    int b; 
                  }
                  

                  我有一个函数,它应该为a"或b"设置一个新值.此函数还需要指定要设置的变量.一个典型的例子是这样的:

                  I have a function which should set a new value for either "a" or "b". This function also requires to specify which variable to set. A typical example would be like this:

                  void f(int which, my_struct* s, int new_value)
                  {
                    if(which == 0)
                       s->a = new_value;
                    else
                       s->b = new_value; 
                  }
                  

                  由于我不会在这里写的原因,我无法将指向 a/b 的指针传递给 f.所以我不能用 my_struct::a 或 my_struct::b 的地址调用 f.我不能做的另一件事是在 my_struct 中声明一个向量 (int vars[2]) 并将一个整数作为索引传递给 f.基本上在 f 我需要按名称访问变量.

                  For reasons I won't write here I cannot pass the pointer to a/b to f. So I cannot call f with address of my_struct::a or my_struct::b. Another thing I cannot do is to declare a vector (int vars[2]) within my_struct and pass an integer as index to f. Basically in f I need to access the variables by name.

                  前面例子的问题是,我打算在未来向 struct 添加更多变量,在这种情况下,我会记得向 f 添加更多 if 语句,这不利于可移植性.我可以做的一件事是将 f 写成一个宏,如下所示:

                  Problem with previous example is that in the future I plan to add more variables to struct and in that case I shall remember to add more if statements to f, which is bad for portability. A thing I could do is write f as a macro, like this:

                  #define FUNC(which)
                  void f(my_struct* s, int new_value) 
                  { 
                          s->which = new_value; 
                  } 
                  

                  然后我可以调用 FUNC(a) 或 FUNC(b).

                  and then I could call FUNC(a) or FUNC(b).

                  这行得通,但我不喜欢使用宏.所以我的问题是:有没有办法使用模板而不是宏来实现相同的目标?

                  This would work but I don't like using macros. So my question is: Is there a way to achieve the same goal using templates instead of macros?

                  编辑:我将尝试解释为什么我不能使用指针并且我需要按名称访问变量.基本上,结构包含系统的状态.该系统需要在请求时撤消"其状态.撤消是使用名为 undo_token 的接口处理的,如下所示:

                  EDIT: I'll try to explain why I cannot use pointers and I need access to variable by name. Basically the structure contains the state of a system. This systems needs to "undo" its state when requested. Undo is handled using an interface called undo_token like this:

                  class undo_token
                  {
                  public:
                     void undo(my_struct* s) = 0;
                  };
                  

                  因此,由于多态性,我无法将指针传递给 undo 方法(mystruct 也包含其他类型的变量).

                  So I cannot pass pointers to the undo method because of polymorphism (mystruct contains variables of other types as well).

                  当我向结构中添加一个新变量时,我通常也会添加一个新类,如下所示:

                  When I add a new variable to the structure I generally also add a new class, like this:

                  class undo_a : public undo_token
                  {
                    int new_value;
                  public:
                    undo_a(int new_value) { this->new_value = new_value; }
                    void undo(my_struct *s) { s->a = new_value}
                  };
                  

                  问题是我在创建令牌时不知道指向 s 的指针,所以我无法在构造函数中保存指向 s::a 的指针(这可以解决问题)."b" 的类是相同的,只是我必须写 "s->b" 而不是 s->a

                  Problem is I don't know pointer to s when I create the token, so I cannot save a pointer to s::a in the constructor (which would have solved the problem). The class for "b" is the same, just I have to write "s->b" instead of s->a

                  也许这是一个设计问题:我需要每个变量类型一个撤消令牌,而不是每个变量一个......

                  Maybe this is a design problem: I need an undo token per variable type, not one per variable...

                  推荐答案

                  #include <iostream>
                  #include <ostream>
                  #include <string>
                  
                  struct my_struct
                  {
                      int a;
                      std::string b;
                  };
                  
                  template <typename TObject, typename TMember, typename TValue>
                  void set( TObject* object, TMember member, TValue value )
                  {
                      ( *object ).*member = value;
                  }
                  
                  class undo_token {};
                  
                  template <class TValue>
                  class undo_member : public undo_token
                  {
                      TValue new_value_;
                      typedef TValue my_struct::* TMember;
                      TMember member_;
                  
                  public:
                      undo_member(TMember member, TValue new_value):
                          new_value_( new_value ),
                          member_( member )
                      {}
                  
                      void undo(my_struct *s) 
                      { 
                          set( s, member_, new_value_ );
                      }
                  };    
                  
                  int main()
                  {
                      my_struct s;
                  
                      set( &s, &my_struct::a, 2 );
                      set( &s, &my_struct::b, "hello" );
                  
                      std::cout << "s.a = " << s.a << std::endl;
                      std::cout << "s.b = " << s.b << std::endl;
                  
                      undo_member<int> um1( &my_struct::a, 4 );
                      um1.undo( &s );
                  
                      std::cout << "s.a = " << s.a << std::endl;
                  
                      undo_member<std::string> um2( &my_struct::b, "goodbye" );
                      um2.undo( &s );
                  
                      std::cout << "s.b = " << s.b << std::endl;
                  
                      return 0;
                  }
                  

                  这篇关于可以使用模板按名称访问结构变量吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:g++/Clang 中的另一个错误?[C++ 模板很有趣] 下一篇:返回转换容器的 std::transform-like 函数

                  相关文章

                  最新文章

                    <legend id='zjGQ6'><style id='zjGQ6'><dir id='zjGQ6'><q id='zjGQ6'></q></dir></style></legend>

                    <small id='zjGQ6'></small><noframes id='zjGQ6'>

                    <i id='zjGQ6'><tr id='zjGQ6'><dt id='zjGQ6'><q id='zjGQ6'><span id='zjGQ6'><b id='zjGQ6'><form id='zjGQ6'><ins id='zjGQ6'></ins><ul id='zjGQ6'></ul><sub id='zjGQ6'></sub></form><legend id='zjGQ6'></legend><bdo id='zjGQ6'><pre id='zjGQ6'><center id='zjGQ6'></center></pre></bdo></b><th id='zjGQ6'></th></span></q></dt></tr></i><div id='zjGQ6'><tfoot id='zjGQ6'></tfoot><dl id='zjGQ6'><fieldset id='zjGQ6'></fieldset></dl></div>
                        <bdo id='zjGQ6'></bdo><ul id='zjGQ6'></ul>

                      <tfoot id='zjGQ6'></tfoot>