Home > Mobile >  C Calling method on members "by name", like Pythons `__getattribute__()`
C Calling method on members "by name", like Pythons `__getattribute__()`

Time:01-21

I want to do something similar to Python's __getattribute()__, but in C . It feels like I should be using some kind of pointer-to-member, but I can't really figure out how to get started.

The gist of what I want to do is define a class that contains pointers to other instances of the same class, as well as various data members. Then I want a method that can be called to do a specific operation, using a specific data member.

For example, if the class is like this:

class C{
    public:
    C* linked1;
    C* linked2;

    double d1;
    double d2;
    
    C(double d1, double d2) : d1{d1}, d2{d2} {};
    double add(<pointer to member or something?>){
        return linked1-><attribute>   linked2-><attribute>   <attribute>
    }
};

I want to be able to call the method add() like this:

C c1{1., 2.};
C c2{3., 4.};
C c3{5., 6.};

c1.linked1 = &c2;
c1.linked2 = &c3;

double a1 = c1.add(<use d1>); // a1 = 1.   3.   5.
double a2 = c1.add(<use d2>); // a2 = 2.   4.   6.

In Python, I would do this with __getattribute__() like this:

class C:
   def __init__(d1, d2):
      self.d1, self.d2 = d1, d2
      self.other1, self.other2 = None, None
   
   def add(attr):
      return self.c1.__getattribute__(attr)   self.c2.__getattribut__(attr)   self.__getattribute__(attr)

c1 = C(1, 2)
c2 = C(3, 4)
c3 = C(5, 6)

c1.other1 = c2
c1.other2 = c2
a1 = c1.add('d1')
a2 = c1.add('d2')

It definitely feels like I should be able to achieve the same type of thing in C without too much hassle. Is this the case? If so, how?

CodePudding user response:

You can't really use a string to get the member without some kind of reflection. However, you can use a pointer to member:

class C {
    double add(double C::* ptr){
        return linked1->*ptr   linked2->*ptr   this->*ptr;
    }
};

Then call it like:

double a1 = c1.add(&C::d1);

Demo

CodePudding user response:

C doesn't have reflection, but you can easily accomplish this task by using a std::(unordered_)map, eg:

#include <map> // or <unordered_map>
#include <string>

class C{
public:
    C* linked1;
    C* linked2;

    std::map<std::string, double> values; // or std::unordered_map
    
    C(double d1, double d2) {
        values["d1"] = d1;
        values["d2"] = d2;
    }

    double add(const std::string& name) const {
        return linked1->values.at(name)   linked2->values.at(name)   values.at(name);
    }
};
C c1{1., 2.};
C c2{3., 4.};
C c3{5., 6.};

c1.linked1 = &c2;
c1.linked2 = &c3;

double a1 = c1.add("d1");
double a2 = c1.add("d2"); 

Online Demo

  • Related