I apologize in advance as this is a rather complex example that I have simplified as much as I can.
http://coliru.stacked-crooked.com/a/f81521f4a4bd6d0d1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
#include <iostream>
#include <memory>
struct Base
{
virtual ~Base() = default;
struct Inner
{
Inner(Base &b)
: inst(b)
{
}
virtual ~Inner() = default;
virtual void f() = 0;
virtual Base &instance()
{
return inst;
}
private:
Base &inst;
};
virtual std::unique_ptr<Inner> new_inner() = 0;
};
struct Derived
: virtual Base
{
Derived(int x)
: v{x}
{
}
struct Inner
: virtual Base::Inner
{
Inner(Derived &d)
: Base::Inner{d}
, inst(d)
{
}
virtual void f()
{
std::cout << inst.v << std::endl;
}
virtual void g(int x) //just a random example
{
inst.v = x;
}
virtual Derived &instance() //fine
{
return inst;
}
private:
Derived &inst;
};
virtual std::unique_ptr<Inner> new_inner() override //problem
{
return std::unique_ptr<Inner>{new Inner{*this}};
}
private:
int v;
};
int main()
{
Derived d {6};
auto inner = d.new_inner();
inner->f();
inner->g(7);
inner->f();
}
|
If I just returned raw pointers, then everything would be ok except that obviously the caller would be responsible for wrapping the returned pointer. I'm trying to find a solution that combines the best of both worlds.
Base and
Derived are the real objects that we're interested in, and they are part of a large inheritance tree. The
Inner classes are directly related to a
Base instance. Each class in the inheritance tree needs its own derived
Inner to specialize its parent's
Inner. If you are given access to an object via
Base, you can create
Inners and call
f(). If you are given access to an object via a
Derived, you can create
Inners and call either
f() or
g(). The creation is handled via the virtual
new_inner() member functions, which let you create
Inner instances for that object type associated with that particular object. There will be multiple overloads and new overloads introduced as you go down the inheritance tree.
Basically, I'm creating polymorphic inner classes. I do have a very good reason for needing this functionality.
I have a solution that is less than ideal, but acceptable:
https://gist.github.com/LB--/51528feec5a44e865abc/revisions (Diff)
http://coliru.stacked-crooked.com/a/5781095ae89bf2c2
Basically, every class implements a copy-paste non-virtual
new_inner() function that just calls
produce_new_inner(). This is terrible code duplication as it is literal copy and paste - they don't even need to be edited.
I could also use a non-member template function to reduce the code duplication but then the syntax isn't as nice and I have to deal with how the template function will have access rights to call the private virtual function. Do recall that there will be many overloads of these functions.
Is there some more ideal solution?