3

Considering the following code/scheme provided below, is it somehow possible to omit the necessity to specify the this?

Is there a way to change the code so that a function/constructor automatically get the surrounding scope, maybe even as a template argument?

#include <iostream>

class AttrBase{
public:
  virtual int g()const = 0;
};

class ABase{
public:
 void reg(const char* name, AttrBase* att){
  std::cout << name << ": " << att->g()<< std::endl;
 }
};


class Attr : public AttrBase{
public: 
  Attr(const char* name, int val, ABase* parent /* = this */) // something like this
   :v(val)
  { 
    parent->reg(name, this);
  };
  int g()const override{return  v;};
  int v;
};


class D:public ABase{
  Attr a{"a", 1, this};
  Attr b{"b", 2, this};
  Attr c{"c", 3};    //< is this somehow possible
};

int main(){
 D d;
}
vlad_tepesch
  • 6,681
  • 1
  • 38
  • 80
  • 1
    What is the purpose of attributes registering themselves with a base class of the class they are a member of? – Michael Kenzel Dec 18 '19 at 15:03
  • 1
    Does this answer your question? [Is there a Modern C++ way for a constructor to know its 'container' class?](https://stackoverflow.com/questions/59308688/is-there-a-modern-c-way-for-a-constructor-to-know-its-container-class) – Botje Dec 18 '19 at 15:11
  • @MichaelKenzel It's not clear by the question, but I suspect the idea here is to make it possible to access the members using string representations of the name. If that's actually a good idea is another question. – super Dec 18 '19 at 15:26

1 Answers1

5

You could add a member-function to ABase that create the Attr for you.

class ABase{
public:
    void reg(const char* name, AttrBase* att) {
        std::cout << name << ": " << att->g()<< std::endl;
    }

protected:
    template <typename AttrType, typename... Args>
    AttrType make(Args&&... args) {
        return AttrType{std::forward<Args>(args)..., this};
    }
};

Then we can use it as

class D:public ABase {
    Attr a = make<Attr>("a", 1);
    auto b = make<Attr>("b", 2); // works with auto to avoid specifying the type twice
};
super
  • 12,335
  • 2
  • 19
  • 29