可以使用模板来按名称访问结构体变量吗? [英] Can templates be used to access struct variables by name?
问题描述
让我们假设我有这样的结构:
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屋!