Handling AngelScript Types

If you are registering functions with variable type argument or template classes, you will definitely need tools to deal with AngelScript types.

Type Traits for Script Type IDs

constexpr bool asbind20::is_void_type(int type_id) noexcept

Check if a type id refers to void.

constexpr bool asbind20::is_primitive_type(int type_id) noexcept

Check if a type id refers to a primitive type.

constexpr bool asbind20::is_enum_type(int type_id) noexcept

Check if a type id refers to an enum type.

constexpr bool asbind20::is_objhandle(int type_id) noexcept

Check if a type id refers to an object handle.

inline bool asbind20::type_requires_gc(const asITypeInfo *ti)

Check if a type requires GC.

This can be used for template callback.

Parameters:

ti – Type information. Null pointer is allowed for indicating primitive type, so it’s safe to call this function by type_requires_gc(ti->GetSubType()).

inline auto asbind20::sizeof_script_type(const asIScriptEngine *engine, int type_id) -> asUINT

Get the size of a script type.

Parameters:
  • engine – Script engine

  • type_id – AngelScript type id

Dispatching Function Calls Based on Type IDs

This feature is similar to how std::visit and std::variant works. It can be used for developing templated container for AngelScript.

template<typename Visitor, void_ptr... VoidPtrs>
decltype(auto) asbind20::visit_primitive_type(Visitor &&vis, int type_id, VoidPtrs... args)

Dispatches pointer of primitive values to corresponding type. Similar to the std::visit.

Warning

This function disallows void type (asTYPEID_VOID)

Parameters:
  • vis – Callable object that can accept all kinds of pointers to primitive types

  • type_id – AngelScript TypeId

  • args – Pointers to primitive values

template<typename Visitor, void_ptr... VoidPtrs>
decltype(auto) asbind20::visit_script_type(Visitor &&vis, int type_id, VoidPtrs... args)

Dispatches pointer of values to corresponding type. Similar to the std::visit.

Note

The object handle will be converted to void**, while script class and registered type will retain as void*

Warning

This function disallows void type (asTYPEID_VOID)

Parameters:
  • vis – Callable object that can accept all kind of pointer

  • type_id – AngelScript TypeId

  • args – Pointers to values

template<typename Visitor>
decltype(auto) asbind20::visit_primitive_type_id(Visitor &&vis, int type_id)

Convert primitive type ID to corresponding std::in_place_type<T>

Template Parameters:

Visitor – Callable that accepts the std::in_place_type<T>

Example code:

asbind20::visit_primitive_type(
    []<typename T>(T* val)
    {
        using type = std::remove_const_t<T>;

        if constexpr(std::same_as<type, int>)
        {
            // play with int
        }
        else if constexpr(std::same_as<type, float>)
        {
            // play with float
        }
        else
        {
            // ...
        }
    },
    as_type_id, // asTYPEID_BOOL, asTYPEID_INT32, etc.
    ptr_to_val // (const) void* to value
);

visit_script_type extends this to non-primitive types — it dispatches primitive types to visit_primitive_type and object handles as void*:

asbind20::visit_script_type(
    []<typename T>(T* begin, T* end)
    {
        using type = std::remove_const_t<T>;

        if constexpr(std::same_as<type, int>)
            std::sort((int*)begin, (int*)end);
        else if constexpr(std::same_as<type, float>)
            std::sort((float*)begin, (float*)end);
        else
        {
            // ...
        }
    },
    type_id,   // any AngelScript type ID
    data_begin,
    data_end
);

If you are certain that types you are dealing with are all primitive types, you can use the primitive-specific function.

inline std::size_t asbind20::copy_primitive_value(void *dst, const void *src, int type_id)

Copy a single primitive value.

Warning

Please make sure the destination has enough space for the value

Parameters:
  • dst – Destination pointer

  • src – Source pointer

  • type_id – AngelScript type id of primitive type

Returns:

Bytes copied

Example code:

// Copy primitive values between void* buffers
int src_int = 42;
int dst_int = 0;

copy_primitive_value(&dst_int, &src_int, asTYPEID_INT32);
assert(dst_int == 42);

// Works for any primitive type
float src_f = 3.14f;
float dst_f = 0.0f;

std::size_t bytes = copy_primitive_value(&dst_f, &src_f, asTYPEID_FLOAT);
assert(bytes == sizeof(float));
assert(dst_f == 3.14f);

// void type copies nothing
std::size_t n = copy_primitive_value(&dst_int, &src_int, asTYPEID_VOID);
assert(n == 0);