可以使用模板来按名称访问结构体变量吗? [英] Can templates be used to access struct variables by name?

查看:110
本文介绍了可以使用模板来按名称访问结构体变量吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设我有这样的结构:

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; 
}

因为我不会在这里写我不能传递指针到/ b到f。所以我不能调用f的地址my_struct :: a或my_struct :: b。
另一件我不能做的是在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,在这种情况下,我将记住添加更多的if语句到f,这是不好的可移植性。
我可以做的事情是写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) 。

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?

EDIT 将尝试解释为什么我不能使用指针,我需要访问变量的名称。
基本上,结构包含系统的状态。该系统需要在请求时撤销其状态。 Undo使用名为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 :: 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

也许这是一个设计问题:每个变量类型都需要一个undo令牌,而不是每个变量一个。

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;
}

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆