In C# 4.0, you can use the "dynamic" keyword as a placeholder for a type that is not known until runtime. There are certain corner cases where this is extremely useful behavior. Is it possible to emulate anything like this in C++, possibly using C++0x features or RTTI?
Not really. The closest you can get is a void *
, but you still need to cast it to an appropriate type before you can use it.
Update:
Trying to build a duck-typed DSL that compiles to C++, basically.
You can go about this in at least two ways:
Union-based variant
struct MyType {
enum { NUMBER, STRING /* etc */ } type;
union {
double number;
string str;
};
};
Polymorphic class heirarchy
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#'s dynamic
feature is highly dependant on .NET's built-in reflection capabilities. As standard C++ offers next to no reflection support, there's no way you can get a similar behavior. RTTI will allow you to safely downcast pointers but that's pretty much it. You're still quite far to being able to enumerate fields and methods and invoke them dynamically.
As others already said this isn't possible in the general case but I think it would be informative to see why not.
There are two levels to the problem, the syntactic level and the semantic level.
On the syntactic level you have the following code:
dynamic d = /* something */;
d.Foo(bar); // Foo is unknown at compile time
In .NET dynamic
is a compiler feature, what it does is instead of generating a function call it creates a call site which contains the function name and types of parameters (for overloading). This means that if you want to support dynamic you have to modify the compiler. It's true that template meta programming allows doing similar stuff but TMP is by its nature done at compile time and therefore won't be up to the job of supporting runtime invocation.
If you're not anal about the syntax then you may be able to support something like this:
dynamic d = /* something */;
d.invoke("Foo", bar);
On the semantic level
As @Trillian (cool user name BTW) said, dynamic relies on reflection, this isn't strictly true, you can specify how dynamic
is implemented, and the default for CLR types is reflection, so the type that bound to a dynamic
variable must support some sort of runtime inspection (e.g. COM's IDispatch
). This isn't true for the general case in C++ but if you can narrow your support only to types that support (a known) type of inspection you can implement dynamic
in C++ (sans the syntax as mentioned above).
It's not possible. Object sizes need to be known at compile-time, so the stack pointer can move by the appropriate number of bytes. If you don't declare the type, then the compiler won't know the size. C# gets around this problem by making all objects pointers.
This example on github provides one possible implementation, depending on your function complexity.
template <typename X, typename Y>
auto add(X x, Y y) -> decltype(x + y) {
return x + y;
}
add(1, 2); // == 3
add(1, 2.0); // == 3.0
add(1.5, 1.5); // == 3.0
I can't think of a possible code path where the type of a value is actually unknown all the way until run-time. Even if you are linking two modules together (dynamically, at run time), both are already compiled, and the types that they can return are also fully determined, and in fact encoded into the mangled names of the symbols the library exposes.
You can, however, defer knowledge of types until the code must actually be compiled. In C++0x, there's the auto
keyword, which provides type inference from the expression used to initialize the variable, and in current C++, you can use templates, like so:
template<typename T>
T square(const T& someArg){
return T*T;
}
Edit: based on your comment on your question, You probably don't have a situation where the type is unknown. What's more likely is that the type is limited to one of a few (predefined) types. for that, you can use a union
type, preferably using boost::variant
© 2022 - 2024 — McMap. All rights reserved.