C++ |处理任意结构成员的类

问题描述 投票:0回答:2

我想要一个具有任意结构类型成员的类。该类应该有一个可以更改结构成员的任意字段值的方法,以及另一个对整个结构成员执行某些操作(例如输出其所有字段)的方法。

我通过以下方式实现了这一点:

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};
行)。相反,我希望结构的实例仅存在于类对象中。我不知道如何实现这一点,但仍然能够改变结构的任意字段。有办法做到这一点吗?

c++ class templates structure
2个回答
1
投票

我自己找到了解决方案。有一种东西叫做“指向成员的指针”。我在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();
}

0
投票

您可以使用指向成员的指针来表示类的特定成员。在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();
}

请参阅此处:https://gcc.godbolt.org/z/Edv8jKM3r

© www.soinside.com 2019 - 2024. All rights reserved.