0

I would like to be able to display different subclasses in a 'human readable' form using a common external function. Printing the 'data' in each instantiation is trivial, but I am struggling with an elegant way to print the details (meta) about the contents of each object.

I can achieve what I want by the following triple of AsData, FieldNames and GetFieldNames. AsData packages the member data in a readable form, FieldNames stores a static list of the data field names for the class at that point in the hierarchy and GetFieldNames wraps FieldNames with an inheritable function:

class A {
public:
    A(const string& name) { /* Setup data */ }

    // ... functions to access data members go here ...

    virtual const vector<string>& GetFieldNames() { 
        return A::FieldNames; 
    }

protected:
    static const vector<string> FieldNames;

    // ... some data members ...
};

class B : public A  {
public:
    B(const string& name, const string& description): A (name) { /* Setup extended data */ }

    // ... functions to access additional data members go here ...

    virtual const vector<string>& GetFieldNames() { 
        return B::FieldNames; 
    }

protected:
    static const vector<string> FieldNames;

    // ... some additional data members ...
};

So the usage could be as follows:

void PrintTable (vector<shared_ptr<A> >& objects) {
    // Print the field names.

    for(const string& name : objects.front()->GetFieldNames())
        cout << name << "\t";

    // ... code to print the actual data goes here ...
}

int main(int argc, char **argv) {
    vector<shared_ptr<A> > myObjects;
    myObjects.push_back(make_shared<B>("Box", "Storage container"));
    myObjects.push_back(make_shared<B>("Glass", "Drink container"));

    PrintTable (myObjects);

    return 0;
}

I would like to ask if it is possible to override a static const member and extend it (I know that sounds like a contradiction) so I can add fields to the static const FieldNames, i.e. something like:

const vector<string> A::FieldNames = {"NAME"};
const vector<string> B::FieldNames = ClassA::FieldNames + {"DESC"}; // Obviously not possible!

I would also be happy to use static const char* const FieldsConst[] instead of vector<string>.

I have looked at this answer and CRTP but I don't think they fit my problem?

TIA :)

Community
  • 1
  • 1
iwbnwif
  • 327
  • 2
  • 13

1 Answers1

0

Okay, I have found a way - it can be done with a lamda. The clue was in this question.

To initialise B::FieldNames as I wanted to, I should use:

const vector<string> B::FieldNames = [] 
    { vector<string> v = A::FieldNames; 
      v.push_back("DESC"); 
      return v; } ();
Community
  • 1
  • 1
iwbnwif
  • 327
  • 2
  • 13