少し難しい条件で、子クラスのインスタンスをその親に動的にキャストする方法を見つけようとしています。
具体的には、次のようなオブジェクト階層があります (大幅に簡略化したので、意味をなさない場合は、簡略化が原因である可能性があります)。
class Object {
public:
virtual ~Object() {}
};
// shown just to give an idea of how Object is used
class IntObject: public Object {
protected:
int value;
public:
IntObject(int v) { value = v; }
int getValue() { return value; }
};
template <class T>
class ObjectProxy: public Object {
protected:
T *instance;
public:
ObjectProxy(T *instance): instance(instance) {}
T *getInstance() { return instance; }
};
このObjectProxy
クラスは基本的にラッパーとして機能し、Object
階層内で他の型を使用できるようにします。具体的には、クラス インスタンスへのポインターを保持し、後でインスタンスのメソッドを呼び出すときに使用できるようにします。たとえば、私が持っているとします:
class Parent {
protected:
int a;
public:
Parent(int v) { a = v; }
virtual ~Parent() {}
void setA(int v) { a = v; }
int getA() { return a; }
};
class Child: public Parent {
protected:
int b;
public:
Child(int v1, int v2): Parent(v1) { b = v2; }
void setA(int v) { b = v; }
int getB() { return b; }
};
次の状況でそれらを使用する可能性があります。
template <typename C>
void callFn(std::list<Object *> &stack, std::function<void (C*)> fn) {
Object *value = stack.front();
stack.pop_front();
ObjectProxy<C> *proxy = dynamic_cast<ObjectProxy<C> *>(value);
if (proxy == nullptr) {
throw std::runtime_error("dynamic cast failed");
}
fn(proxy->getInstance());
}
void doSomething(Parent *parent) {
std::cout << "got: " << parent->getA() << std::endl;
}
int main() {
std::list<Object *> stack;
// this works
stack.push_back(new ObjectProxy<Child>(new Child(1, 2)));
callFn<Child>(stack, doSomething);
// this will fail (can't dynamically cast ObjectProxy<Child> to ObjectProxy<Parent>)
stack.push_back(new ObjectProxy<Child>(new Child(1, 2)));
callFn<Parent>(stack, doSomething);
}
上記のコメントで述べたように、このコードは既知の理由で失敗します。サンプル コードでは、呼び出しを避けるのは簡単callFn<Parent>(stack, doSomething)
です。ただし、実際のコードでは、関数のシグネチャを使用して型を決定しています。親クラスのメソッドである場合は、テンプレート パラメーターに自動的に使用されます。
私の質問は、ObjectProxy のタイプのオブジェクトから ObjectProxy からの動的キャストを実現する方法があるかどうかです。callFn
複雑さの一部は、 functionで、子の型ではなく親の型しか持たないという事実から来ています。
type-erasure via の使用を検討しましたboost::any
(つまりObjectProxy
、テンプレート化を停止し、代わりに を使用しました) が、動的キャスト ( is static )boost::any instance
に関してはまだ問題に遭遇しました。boost::any_cast
SOに関する言及を見つけましたdynamic_any
が、まだ適切に機能していません。
問題への助けや洞察は大歓迎です。