0

I have a class that contains a tree structure implemented by a vector< vector< Node > > where Node contains a bunch of attributes exposed via getters/setters.

class Tree
{
   vector< vector< Node > > mGrid;
   printTree(std::ostream& output = std::cout);
};

class Node
{
   double property1 { return mProp1; }
   double property2 { return mProp2; }
};

printTree() is currently hardwired to use property tstep:

void Tree::printTree( ostream& output )
{
   ...
   for (unsigned t = 0; t < mGrid.size(); ++t)
   {
      toPrint = "";

      for (unsigned state = 0; state < mGrid[t].size(); ++state)
      {

         toPrint += to_string_with_precision( mGrid[t][state].tstep(), 1 );

         ...

Is there some slick / convenient / object-oriented way of generalizing this function so that it can print out any of Node's properties (rather than only spitting out the hardwired tstep() property or essentially doing the same thing via if/then statements).

I've done things like this in C using function pointers, but this is C++ and the C++ FAQ says not to mess with pointers to member functions.

Mathematician
  • 380
  • 2
  • 9
  • 1
    What you *really* want (I think) is "reflection" - which is not (yet) part of the C++ standard. :-/ this may interest you: https://meetingcpp.com/index.php/br/items/reflections-on-the-reflection-proposals.html – Jesper Juhl Aug 24 '17 at 18:20
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a [mcve]. Use the "edit" link to improve your *question* - do not add more information via comments. Thanks! – GhostCat Aug 24 '17 at 19:11

2 Answers2

0

You might want template function:

class Tree
{
   vector< vector< Node > > mGrid;
public:
   template <typename F>
   void ForEachNode(F&& f) {
       int i = 0;
       for (auto& v : mGrid) {
           int j = 0;
           for (auto& node : v) {
               f(node, i, j);
               ++j;
           }
           ++i;
       }
   }
};

Then you may do

void printTreeProp1(Tree& tree) {
    tree.ForEachNode([](const Node& node, int i, int j) {
         if (i != 0 && j == 0) {
             std::cout << std::endl;
         }
         std::cout << node.property1() << " ";
    });
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

1st op all you loops are ignoring the first element. vector is zero based and you are using ++t and ++state which increases the values on top of the loop. That means you are never accessing the 0th element (mGrid[0] and mGrid[t][0]).
2nd, you did noy include the definition of tstep(), so we don't know what you are getting back. Assuming you want to print each dimension of your 2 dimension array, I think you have to break it to peaces. Something like this:

class Node
{
protected:
    double mProp1;
    double mProp2;

public:
    double GetProp1(void) {return mProp1;}
    double GetProp2(void) {return mProp2;}
    String tStep(void) {return L"";}   // add your code here
};

class NodeRow : public std::vector<Node>
{
public:
    void Print(std::ostream& output)
    {
        iterator i;
        String tStr;

        for(i = begin(); i != end(); i++)
            tStr += /*to_string_with_precision(*/i->tStep()/*, 1)*/;
        output << tStr.c_str() << L"\r\n";
    }
};

class Node2D : public std::vector<NodeRow>
{
public:
    void Print(std::ostream& output = std::cout)
    {
        iterator i;

        for(i = begin(); i != end(); i++)
            i->Print(output);
    }
};
Sam
  • 2,473
  • 3
  • 18
  • 29
  • I disagree. The control variable is tested at the bottom. Using pre or post increment doesn't matter. See https://stackoverflow.com/questions/4706199/post-increment-and-pre-increment-within-a-for-loop-produce-same-output – Mathematician Aug 24 '17 at 19:44
  • @Mathematician I am talking about the first time it enters the loop. by the time you get to the `[]` operator the value of `t` and `state` is 1 not 0. The testing part is correct. The code as you wrote it, skips the 0th elements. At the very least you should use `t++` and `state++`. Just debug the code and you will see what I am talking about. – Sam Aug 24 '17 at 20:53
  • @Mathematician Also keep in mind iterators are much better (faster) than indexes. – Sam Aug 24 '17 at 20:55
  • @Mathematician [this](https://stackoverflow.com/questions/484462/difference-between-i-and-i-in-a-loop) explains better what I am talking about. – Sam Aug 24 '17 at 21:09