5
votes

I'm trying to design a class that can be built from an inner class. The way I am trying to accomplish this is by having a class to be built contain a nested builder class. This nested class design is attractive to me because it automatically associates my builder class with the class it is going to build.

The trouble is, I get the following compiler error when compiling with g++ (8.3.0): field 'v' has incomplete type 'Vector'.

I have included an example that illustrates the problem I am encountering. Of course, this example is just a more obscure way of building a std::vector. However, in my project, I believe this design pattern is justified because the builder class is doing more work on top of just replacing the std::vector<>::push_back method.

I have tried searching for solutions to this problem, but all my results are questions about the access policy between inner and outer class members and not about the inner class actually having the outer class as a member.

#include <vector>

class Vector : public std::vector<int> {
public:
  class Builder {
  public:
    Builder &add(int const i) {
      v.push_back(i);
      return *this;
    }

    Vector build() const {
      return v;
    }

  private:
    Vector v;
  };
};

int main() {
  Vector v = Vector::Builder().add(1).add(2).add(3).build();

  return 0;
}

I know I can just move the inner builder class outside of the class it is building, but I like that the builder class is automatically scoped inside the outer class.

I feel like there must be an easy solution to this problem although I am also afraid there might be some sort of recursion problem if I do manage to solve this first error. Maybe there is someway to 'complete' the definition of the outer class before I define the inner class.

Any suggestions are appreciated.

1
class Vector : public std::vector<int> you shouldn't inherit from c++ standard container classes. - πάντα ῥεῖ
My eyes cannot distinguish between an upper V and a lower v - Amadeus
@πάνταῥεῖ Thanks for informing me, I did not know this. I looked up why this can be bad and decided to not do this in my project, instead I will use composition in this case. - Pavis11
@Amadeus Sorry about that! I was trying to keep it simple in the example, in my project my outer class is named more appropriately and does not represent a vector of integers, but a vector of some other class in the project. - Pavis11
@Pavis11 on my screen, under code formatting, upper V is diferent from lower v by 1 pixel. A kind of hard to distinguish between them - Amadeus

1 Answers

6
votes

You can move the definition of the inner class outside the outer definition

class Outer 
{
    public:
        class Inner;
};

class Outer::Inner
{
    // As before
};