C# 4.0 では、実行時まで不明な型のプレースホルダーとして "dynamic" キーワードを使用できます。これが非常に便利な動作である特定のまれなケースがあります。おそらくC++0x機能またはRTTIを使用して、C++でこのようなものをエミュレートすることは可能ですか?
6 に答える
あまり。最も近いのは ですが、void *
使用する前に適切な型にキャストする必要があります。
アップデート:
基本的に、C++ にコンパイルされるダック型の DSL を構築しようとしています。
これには、少なくとも 2 つの方法があります。
ユニオンベースのバリアント
struct MyType {
enum { NUMBER, STRING /* etc */ } type;
union {
double number;
string str;
};
};
ポリモーフィックなクラス階層
class MyType {
public:
/* define pure virtual operations common to all types */
};
class MyNumber : public MyType {
private:
double number;
public:
/* implement operations for this type */
};
C# のdynamic
機能は、.NET の組み込みリフレクション機能に大きく依存しています。標準の C++ ではリフレクションがほとんどサポートされていないため、同様の動作を実現する方法はありません。RTTI を使用すると、ポインタを安全にダウンキャストできますが、それだけです。フィールドとメソッドを列挙し、それらを動的に呼び出すことができるようになるには、まだかなりの時間がかかります。
他の人がすでに言ったように、これは一般的なケースでは不可能ですが、なぜそうでないのかを知ることは有益だと思います.
問題には、構文レベルと意味レベルの 2 つのレベルがあります。
構文レベルでは、次のコードがあります。
dynamic d = /* something */;
d.Foo(bar); // Foo is unknown at compile time
.NET ではdynamic
コンパイラ機能です。関数呼び出しを生成する代わりに、関数名とパラメーターの型 (オーバーロード用) を含む呼び出しサイトを作成します。これは、動的をサポートする場合は、コンパイラを変更する必要があることを意味します。テンプレート メタ プログラミングで同様の処理が可能であることは事実ですが、TMP はその性質上コンパイル時に実行されるため、ランタイム呼び出しをサポートすることはできません。
構文について肛門ではない場合は、次のようなものをサポートできる場合があります。
dynamic d = /* something */;
d.invoke("Foo", bar);
セマンティック レベル
@Trillian (クールなユーザー名 BTW) が言ったように、動的はリフレクションに依存しています。これは厳密には真実ではありません。実装方法を指定できます。CLR型のデフォルトはリフレクションであるため、にバインドされた型は変数は、ある種のランタイム インスペクション (COM など) をサポートする必要があります。これは C++ の一般的なケースには当てはまりませんが、(既知の) タイプの検査をサポートするタイプのみにサポートを絞り込める場合は、C++ で実装できます (上記の構文は不要です)。dynamic
dynamic
IDispatch
dynamic
不可能です。オブジェクトサイズはコンパイル時に知る必要があるため、スタックポインタは適切なバイト数で移動できます。タイプを宣言しない場合、コンパイラはサイズを認識しません。C#は、すべてのオブジェクトをポインターにすることでこの問題を回避します。
値のタイプが実行時までずっと不明である可能性のあるコードパスを考えることはできません。2つのモジュールを(動的に、実行時に)リンクしている場合でも、両方とも既にコンパイルされており、返すことができるタイプも完全に決定されており、実際には、ライブラリが公開するシンボルのマングル名にエンコードされています。
ただし、コードを実際にコンパイルする必要があるまで、型の知識を延期することができます。C ++ 0xにはauto
、変数の初期化に使用される式から型推論を提供するキーワードがあり、現在のC ++では、次のようなテンプレートを使用できます。
template<typename T>
T square(const T& someArg){
return T*T;
}
編集:あなたの質問に対するあなたのコメントに基づいて、あなたはおそらくタイプが不明であるという状況を持っていないでしょう。より可能性が高いのは、タイプがいくつかの(事前定義された)タイプの1つに制限されていることです。union
そのためには、タイプを使用できます。boost::variant