2016-08-04 11 views
-1

混乱するタイトルについては、どうしても言い方がわかりません。 私がしようとしているのは、基本的にマップから動的に取り出される型にキャストされます。 (マップにはインスタンスはありませんが、可能であればタイプがあります)オブジェクトの型をキャスト目的のマップに格納することは可能ですか?

例を使って説明することができます。私はbaseFoo

class baseFoo 
{ 
} 

と呼ばれる基本クラスを持っているし、私はbaseFooから継承今すぐ

class derfooB : public baseFoo 
{ 
} 

derfooBについても同様にderFooAderFooB

class derfooA : public baseFoo 
{ 
} 

とと呼ばれる2つの異なるクラスがあるとし 私はマップに型を格納できるかどうかを知りたがっています(型のインスタンスではありません - 単純に変数の型)この

//STATEMENT A: 
std::map<std::string , baseFoo> myMap= {{"derfooA",derfooA}, {"derfooB", derfooB}}; 

のようなものは、それから私はこのような何かをしたいと思います:

私は baseFoo PTRを持っていると言うと、私はに基づいて、特定のタイプにPTRを意気消沈したいと思います文字列。このようなメカニズムは、私の文がどのように見えるかだろうことも可能である場合

std::string str = "derfooA"; 
derfooA* dfoo = dynamic_cast<myMap[str]>(baseFoo_ptr) 

今私の質問は次のとおりです。だから私は、これを行うことができますか?

+0

'dynamic_cast'ステートメントの' derFooA'は、あなたがターゲットタイプを知っていることを示唆しています。 – aschepler

+3

あなたはどんな問題を解決しようとしていますか?なぜあなたはダウンキャストが必要ですか? – Barry

+0

特定の型にキャストしようとしていますが、この型は文字列から判断されます。これを達成するために、私はマップを使用しているその目的のための型に文字列をマップすることをお勧めします –

答えて

2
template<class...Ts> 
struct types { using type=types; }; 

これは種類のバンドルです。

template<class T>struct tag_t{constexpr tag_t(){}; using type=T;}; 
template<class T>constexpr tag_t<T> tag{}; 

これはタイプタグです。

これにより、タグに基づいて動的キャストを送信できます。

template<class F, class Sig> 
struct invoker; 
template<class F, class R, class...Args> 
struct invoker<F, R(Args...)> { 
    R(*)(void*, Args...) operator()() const { 
    return [](void* ptr, Args...args)->R { 
     return (*static_cast<F*>(ptr))(std::forward<Args>(args)...); 
    }; 
    } 
}; 
template<class F, class...Sigs> 
std::tuple<Sigs*...> invokers() { 
    return std::make_tuple(invoker<F, Sigs>{}()...); 
} 

ので、この時点で、我々は署名各署名用Sigsのセットと、指定されたオブジェクトFタイプを呼び出す関数へのポインタの組を有しています。

我々は次のvoid*最初の引数でSigs*std::tupleに基づいて、それにはいくつかの呼び出しに基づいてSigs...から「右」Sigsを選択することになるdipatcherを記述します。

ここでは、キャスト先にサポートしたいタイプのtypes<...>を取ります。渡されたラムダを格納する型消去クラスを生成するために、これをstd::unique_ptr<void, void(*)(void*)>に使用します。サポートする署名はtag_t<x>です。xのタイプはtypes<x...>で異なります。

これはあなたのダイナミックディスパッチャーです。

ほとんどの方法があります。次に、動的ディスパッチャとvoid*をとり、tag_t<x>でそれを呼び出します。それは、インターフェイスがそれを公開しないように動的ディスパッチャを呼び出すを消去します。これは基本的に、この時点でstd関数へのバインダーです。

//STATEMENT A: 
std::map<std::string , helper<derFooA, derFooB>> myMap= 
    {{"derfooA",tag<derfooA>}, {"derfooB", tag<derfooB>}}; 
myMap[str]([&](auto&& tag) { 
    auto* dfoo = tag_dynamic_cast(tag, baseFoo_ptr); 
}); 

及びラムダはすべての派生タイプのためにインスタンス化されるが、ランであろう唯一のマップに格納されている値と一致するものです。

あなたはラムダ内に閉じ込められていることに気づくでしょう。うん実行時の状態以外では、実際の型情報を "漏らす"ことはできません。

今、あなたの本当の問題は簡単な解決策です。しかし、これはどのようにそれを行うためのロードマップです。私はそれを自分で書くのに時間がかかります。

0

ストアインスタンス内のタイプ、このような何か:

class baseFoo 
{ 
public: 
class enum eClass 
{ 
    a, 
    b, 
} myType; 

baseFoo(eClass type) 
: myType(type) 
{} 
eClass getType() { return myTpe; }| 
}; 

class derfooA : public baseFoo 
{ 
public: 
    derfooA() 
    : baseFoo(baseFoo::eClass::a) 
    {} 
}; 

... 

baseFoo * ptr; 

... 

switch(ptr->getType()) { 
    case baseFoo::eClass::a: 
    ... do something 
関連する問題