NAME

@dynamic_cast - Safely cast an object to a different type at runtime

SYNOPSIS

@dynamic_cast<CLASS-NAME[*]> {INPUT}
@dynamic_cast<$shell_variable> {INPUT}
@dynamic_cast<@object.reference> {INPUT}

DESCRIPTION

The @dynamic_cast operator is used to safely cast an object to a different type at runtime. The directive is expanded to the result described below.

The result of the @dynamic_cast directive will be either:

To determine whether a cast is valid, @dynamic_cast automatically follows any level of pointer indirection. If INPUT is a pointer to a pointer (or a deeper chain of pointers), the chain is repeatedly dereferenced until the actual object is reached. The output then will not be the address of the original pointer, or of any intermediate pointer, but the address of the actual object, if it can be safely cast to the specified type.

TARGETS

The target of the @dynamic_cast directive is the type to which you want to cast the object. The target is given in the <...> bracket pair and can be one of the following:

If a class name is given directly, the compiler will emit a warning if the class is not defined in the current context.

If a shell variable or object reference is given, the compiler will expect to resolve the class name at runtime.

If an object reference is given, it can refer to either a data member or a method. I.e., all kinds of object references are acceptable here. If the reference refers to a method, that method will be implicitly executed in a supershell, and its output will be treated as the target class name.

EXAMPLE

The safest way to use @dynamic_cast is to specify the target class name directly:

@Object obj

@Object* castedObj=@dynamic_cast<Object> &@obj # Successful cast of obj to Object pointer

@castedObj=@dynamic_cast<Object> "Hello, world!" # Failed cast, returns @nullptr

shell_variable=@dynamic_cast<Object*> &@obj # Successful cast, pointer stored in $shell_variable

@UnrelatedObject unrelatedObj

echo @dynamic_cast<Object> &@unrelatedObj # Failed cast, echoes @nullptr

However, we can also give a shell variable or an object reference as the target class. In this case, no warnings will be emitted, and the class name will be resolved at runtime:

@class Object {
	@public member="Object"
}

shell_var="Object"

@Object obj

@Object* castedObj=@dynamic_cast<$shell_var> &@obj # Successful cast of obj to 'Object'

@Object* castedObj2=@dynamic_cast<@obj.member> &@obj # Successful cast of obj to 'Object'

@obj.member="NotARealClass"

@castedObj=@dynamic_cast<@obj.member> &@obj # Failed cast, no class called 'NotARealClass' exists, returns @nullptr

NOTES

EXPANSION

The @dynamic_cast directive expands to the result described above. This result is then interpreted according to the shell context in which the directive is used. For example, if the directive is used in a context where a command is expected, the result will be treated as a command. If it is used in a context where an argument is expected, the result will be treated as an argument.

echo @dynamic_cast<Object> @ptr # Passes the result as an argument to 'echo'
var=@dynamic_cast<Object> @ptr  # This assigns the result to a variable
@dynamic_cast<Object> @ptr      # Watch out! This attempts to run the result as a command; you'll probably see "command not found."

INPUT

The input to the @dynamic_cast directive is that which is being casted. It is typically a pointer to an object, but it may be any rvalue at all, including a call to a method, a simple string, a supershell/subshell, etc. Of course, in most cases, the input should be a pointer to an object.

CAST VALIDITY

The validity of a @dynamic_cast is determined at runtime. The directive will only succeed if the object being cast is actually an instance of the target class itself, or of a class derived from the target class. If the cast is invalid, the result will be @nullptr.

USAGE

The @dynamic_cast directive is most useful when the type of the object is not known at compile time, or when the object may be of a different type than expected.

You can safely verify that a cast was successful by checking if the result is @nullptr. If it is not, you can safely use the result as a pointer to the specified type.

@DerivedClass derived_object
@BaseClass* myPointer=@dynamic_cast<BaseClass> &@derived_object

if [[ @myPointer == @nullptr ]]; then
	echo "The cast is invalid"
else
	echo "All OK!"
fi

SEE ALSO