创建宏为任何 class c++ 生成 getter
Create macro to generate getters for any class c++
最近我开始考虑如何通过名称的通用化 class/function 来通用化对私有数据成员的访问。原因是我有很多私有成员,为每个成员创建一个 getter 很麻烦。我尝试使用预处理器宏来执行以下操作
#define RETURNS(...) -> decltype((__VA_ARGS__)) { return (__VA_ARGS__); }
#define GET(classname, name, funcname) auto funcname() RETURNS(classname->name);
class foo {
private:
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
foo() = default;
~foo() = default;
GET(this, a, getter);
};
int main(const int argc, char* argv[]) {
foo obj;
std::cout << obj.getter();
return 0;
}
这个可以编译,但是有没有一种方法可以在 foo
中创建一个 getter,它采用 运行 时间和 returns 的变量名称] this->(name)
?使用这种方法,我可以减少引入 getters 的代码,但是数据成员越多,我需要的 getters 就越多,但我希望有一个可以访问任何数据成员按名字。您对如何完成有任何建议吗?
我正在寻找这样的语法:
#define RETURNS(...) -> decltype((__VA_ARGS__)) { return (__VA_ARGS__); }
#define GET(classname, name) RETURNS(classname->name);
class foo {
private:
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
foo() = default;
~foo() = default;
auto getter(auto x) GET(this, x);
};
这里x
是我输入的名字,a
、b
或者c
Do you have any suggestion of how can it be done?
为什么所有 decltype
和 ->
以及带有 __VA_ARGS__
和 RETURNS
的可变参数宏...只是:
#include <vector>
#include <string>
#define DECL_GETTER(name) \
auto get_##name() { return this->name; }
class foo {
private:
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
DECL_GETTER(a)
DECL_GETTER(b)
DECL_GETTER(c)
};
int main() {
foo f;
f.get_a();
f.get_b();
f.get_c();
}
我还会添加 const
重载。
你可能想研究一下QT properties system,那基本上就像是这个的更高级版本。
主观:TBH 使用这样一个宏,你在不需要它们的地方进行抽象。值得花时间吗?它用 non-obvious 宏隐藏了一些明显的代码,使 IDE 更难“跳转到定义”,使维护和推理更难。重命名具有 IDE 特征的变量会更难。考虑逐字逐句地手工编写这些 getter - 考虑第一眼看上去显而易见的可读且清晰的代码,即使您不得不牺牲一点重复并键入更多 () { return
个字符。配置你的IDE,这样你就可以“为这个成员函数创建一个getter/setter”动作来加速你的开发(例如QT Creator,这是一个非常好的功能)。
is there a way I can create a getter in foo, which takes the name of a variable at run-time and returns this->(name)?
C++ 是一种没有 reflection 的语言,所以基本上不需要,否则它需要的样板代码远远超过它的价值。
修订:
如@HolyBlackCat所述,不需要堆分配,你应该直接使用impl
class作为对象:
class foo{
struct foo_data
{
int i;
std::string s;
};
foo_data data;
public:
template<typename ... Args>
foo(Args&& ... args)
: data(std::forward<Args>(args)...)
{}
foo_data const* operator->() const // Returns a pointer to const data
{
return &data;
}
};
然后访问数据:
int main()
{
auto f = foo(3, "hello");
std::cout << f->i << f->s; // Accessing data, prints: "3hello"
// f->i += 1; // Error: assignment of member in read-only object
}
最近我开始考虑如何通过名称的通用化 class/function 来通用化对私有数据成员的访问。原因是我有很多私有成员,为每个成员创建一个 getter 很麻烦。我尝试使用预处理器宏来执行以下操作
#define RETURNS(...) -> decltype((__VA_ARGS__)) { return (__VA_ARGS__); }
#define GET(classname, name, funcname) auto funcname() RETURNS(classname->name);
class foo {
private:
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
foo() = default;
~foo() = default;
GET(this, a, getter);
};
int main(const int argc, char* argv[]) {
foo obj;
std::cout << obj.getter();
return 0;
}
这个可以编译,但是有没有一种方法可以在 foo
中创建一个 getter,它采用 运行 时间和 returns 的变量名称] this->(name)
?使用这种方法,我可以减少引入 getters 的代码,但是数据成员越多,我需要的 getters 就越多,但我希望有一个可以访问任何数据成员按名字。您对如何完成有任何建议吗?
我正在寻找这样的语法:
#define RETURNS(...) -> decltype((__VA_ARGS__)) { return (__VA_ARGS__); }
#define GET(classname, name) RETURNS(classname->name);
class foo {
private:
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
foo() = default;
~foo() = default;
auto getter(auto x) GET(this, x);
};
这里x
是我输入的名字,a
、b
或者c
Do you have any suggestion of how can it be done?
为什么所有 decltype
和 ->
以及带有 __VA_ARGS__
和 RETURNS
的可变参数宏...只是:
#include <vector>
#include <string>
#define DECL_GETTER(name) \
auto get_##name() { return this->name; }
class foo {
private:
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
DECL_GETTER(a)
DECL_GETTER(b)
DECL_GETTER(c)
};
int main() {
foo f;
f.get_a();
f.get_b();
f.get_c();
}
我还会添加 const
重载。
你可能想研究一下QT properties system,那基本上就像是这个的更高级版本。
主观:TBH 使用这样一个宏,你在不需要它们的地方进行抽象。值得花时间吗?它用 non-obvious 宏隐藏了一些明显的代码,使 IDE 更难“跳转到定义”,使维护和推理更难。重命名具有 IDE 特征的变量会更难。考虑逐字逐句地手工编写这些 getter - 考虑第一眼看上去显而易见的可读且清晰的代码,即使您不得不牺牲一点重复并键入更多 () { return
个字符。配置你的IDE,这样你就可以“为这个成员函数创建一个getter/setter”动作来加速你的开发(例如QT Creator,这是一个非常好的功能)。
is there a way I can create a getter in foo, which takes the name of a variable at run-time and returns this->(name)?
C++ 是一种没有 reflection 的语言,所以基本上不需要,否则它需要的样板代码远远超过它的价值。
修订:
如@HolyBlackCat所述,不需要堆分配,你应该直接使用impl
class作为对象:
class foo{
struct foo_data
{
int i;
std::string s;
};
foo_data data;
public:
template<typename ... Args>
foo(Args&& ... args)
: data(std::forward<Args>(args)...)
{}
foo_data const* operator->() const // Returns a pointer to const data
{
return &data;
}
};
然后访问数据:
int main()
{
auto f = foo(3, "hello");
std::cout << f->i << f->s; // Accessing data, prints: "3hello"
// f->i += 1; // Error: assignment of member in read-only object
}