-1

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')

I feel like I am looking for a kind of pointer-to-member, but can't figure out how to make it work.

Edit, for clarity:

What I have is a Node-class that contains a bunch of properties (temperature, pressure, composition, etc.) and is linked to its neighbouring nodes. I want to be able to use one method to compute for example the interpolation polynomial for a property.

It feels like bad practice to write a dedicated method to interpolate each property, when the math is identical. The same is true for any other mathematical operation that uses a node and its neighbours.

Writing a separate method for each property also reduces scalability, as introducing a new property would require that one also writes new methods to compute gradients, interpolation coefficients, etc. for that property. I would argue that it is definitely cleaner (and less bug-prone) to be able to introduce a new property, and simply call a generic method using a pointer to member.

  • Names are for useless, inferior organics. Machines need no names. Machines use addresses and offsets. Compilers remove the names in order to reach a level of logical purity organics will never attain. Abandon names. Embrace perfection! – user4581301 Jan 21 '23 at 01:14
  • *I want to do something similar to pythons __getattribute()__, in C++* -- I'm sorry, but to me, what you are doing in python seems convoluted. To that, I'm glad C++ has nothing like that. Instead, why not have an array of double, and pass in the index of the values you want to add? – PaulMcKenzie Jan 21 '23 at 05:04
  • @PaulMcKenzie "Why not use an array", because this is a minimal example, and my real data structure contains too many variables than what would be feasible to remember indices for. That approach would also make it less readable. As for why: When computing eg. gradients, convolutions, etc. I feel it would be clean to have *one* method to do the same mathematical operation for all properties. This also improves scalability when I add new properties to the structure, as I won't need to re-implement identical methods for each property. – Vegard Gjeldvik Jervell Jan 22 '23 at 11:24

2 Answers2

2

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

Ranoiaetep
  • 5,872
  • 1
  • 14
  • 39
  • 1
    THANK YOU! I knew i was close about the , but couldn't figure out the syntax. Also, thank you for answering after others have said stuff like "this is a bad idea, and I'm glad you can't do it in c++" :) – Vegard Gjeldvik Jervell Jan 22 '23 at 08:47
1

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

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770