我想要一个具有任意结构类型成员的类。该类应该有一个可以更改结构成员的任意字段值的方法,以及另一个对整个结构成员执行某些操作(例如输出其所有字段)的方法。
我通过以下方式实现了这一点:
struct myStruct1
{
int age;
double height;
};
struct myStruct2
{
float weight;
};
template<typename T, typename S>
class myClass
{
public:
myClass(T& structure, S& field)
: _structure {structure}
, _field {field}
{}
void alterField(double newVal)
{
_field = static_cast<S>(newVal);
}
void outputFields()
{
// code that outputs fields
// uses _structure
// otherwise not important
}
private:
T& _structure;
S& _field;
};
int main() {
myStruct1 structInstance1 {14, 1.63};
myClass<myStruct1, int> classInstance1 {structInstance1 , structInstance1.age};
myStruct2 structInstance2 {75.6};
myClass<myStruct2, float> classInstance2 {structInstance2, structInstance2.weight};
classInstance1.alterField(15);
classInstance1.outputFields();
classInstance2.alterField(73.8);
classInstance2.outputFields();
}
但是,我每次都必须以这种方式实例化结构(参见第
myStruct1 structInstance1 {14, 1.63};
行)。相反,我希望结构的实例仅存在于类对象中。我不知道如何实现这一点,但仍然能够改变结构的任意字段。有办法做到这一点吗?
我自己找到了解决方案。有一种东西叫做“指向成员的指针”。我在here找到了解释。使用它,我上面的示例代码如下所示:
#include <iostream>
struct myStruct1
{
int age;
double height;
};
struct myStruct2
{
float weight;
};
template<typename T, typename S>
class myClass
{
public:
myClass(T structure, S T::* ptr_field)
: _structure {structure}
, _ptr_field {ptr_field}
{}
void alterField(double newVal)
{
_structure.*_ptr_field = static_cast<S>(newVal);
}
void outputFields()
{
std::cout << _structure.*_ptr_field << "\n";
}
private:
T _structure;
S T::* _ptr_field;
};
int main() {
myClass<myStruct1, int> classInstance1 {myStruct1{14, 1.63}, &myStruct1::age};
classInstance1.alterField(15);
classInstance1.outputFields();
myClass<myStruct2, float> classInstance2 {myStruct2{75.6}, &myStruct2::weight};
classInstance1.alterField(73.8);
classInstance1.outputFields();
}
您可以使用指向成员的指针来表示类的特定成员。在C++20中,你可以这样做:
template<auto MP>
class myClass
{
template <typename C, typename M> static C owner(M C::*);
template <typename C, typename M> static M member(M C::*);
using T = decltype(owner(MP));
using FT = decltype(member(MP));
public:
template <typename... Args>
explicit myClass(Args&&... args)
: _structure {args...}
{}
void alterField(double newVal)
{
_structure.*MP = static_cast<FT>(newVal);
}
void outputFields()
{
// code that outputs fields
// uses _structure
// otherwise not important
}
private:
T _structure;
};
int main() {
myClass<&myStruct1::age> classInstance1 {14, 1.63};
myClass<&myStruct2::weight> classInstance2 {75.6f};
classInstance1.alterField(15);
classInstance1.outputFields();
classInstance2.alterField(73.8);
classInstance2.outputFields();
}