Comparing Script Objects

When implementing a container for script objects, you need a way to compare elements — for operator==, operator<=>, std::sort, or deduplication. AngelScript classes can define opEquals and opCmp methods, but calling them from C++ requires discovering them at runtime.

container/compare.hpp provides tools to inspect a script type for these methods and invoke them through a uniform interface.

Note

The content of this file is designed for library developers implementing containers. If you are not building a custom container for script objects, you likely do not need these APIs.

Discovering Comparators

Call get_comparator with an asITypeInfo* to scan the type’s methods. It looks for methods matching these signatures:

  • bool opEquals(const T&in) const

  • int opCmp(const T&in) const

#include <asbind20/container/compare.hpp>

asITypeInfo* ti = /* ... */;

auto result = asbind20::container::get_comparator(ti);
auto status = result.get_status();

if(status.opCmp >= 0) {
    // type has opCmp
}
if(status.opEquals >= 0) {
    // type has opEquals
}
if(!status.good()) {
    // neither method found — type is not comparable
}

asbind20::container::script_element_comparator cmp = result.get();

Using the Comparator

Once obtained, script_element_comparator provides eq() and compare() that invoke the discovered script methods. Both take a script context and two const void* pointers to the elements.

asIScriptContext* ctx = /* ... */;
const void* lhs = /* pointer to first element */;
const void* rhs = /* pointer to second element */;

// Check equality — uses opEquals when available, otherwise falls back to opCmp() == 0
if(cmp.eq(ctx, lhs, rhs)) {
    // elements are equal
}

// Compare — returns std::partial_ordering (unordered if comparison fails or is unavailable)
std::partial_ordering ord = cmp.compare(ctx, lhs, rhs);
if(ord < 0) {
    // lhs < rhs
} else if(ord == 0) {
    // lhs == rhs
} else if(ord > 0) {
    // lhs > rhs
}

// For more control, invoke the underlying script_method objects directly:
auto eq_result = cmp.invoke_eq(ctx, lhs, rhs);
if(eq_result.has_value() && eq_result.value()) {
    // ...
}

Checking Availability

if(cmp.has_opEquals()) { /* opEquals is available */ }
if(cmp.has_opCmp())    { /* opCmp is available */ }
if(cmp)                 { /* at least one comparison method exists */ }

Integration with Containers

A typical pattern for a container implementing operator==:

template <typeinfo_policy TypeInfoPolicy>
bool my_container::operator==(const my_container& other) const
{
    if(this->size() != other.size())
        return false;

    auto cmp = container::get_comparator(this->element_type_info()).get();
    if(!cmp)
        return false; // not comparable — treat as not equal

    request_context ctx(this->get_engine());
    for(std::size_t i = 0; i < this->size(); ++i) {
        if(!cmp.eq(ctx, (*this)[i], other[i]))
            return false;
    }
    return true;
}
class script_element_comparator

Public Types

using opEquals_type = script_method<bool(const void*)>
using opCmp_type = script_method<int(const void*)>

Public Functions

script_element_comparator() = default
script_element_comparator(const script_element_comparator&) = default
script_element_comparator &operator=(const script_element_comparator&) = default
inline script_element_comparator(asIScriptFunction *opCmp, asIScriptFunction *opEquals)
inline const opEquals_type &get_opEquals() const noexcept
inline bool has_opEquals() const noexcept
inline const opCmp_type &get_opCmp() const noexcept
inline bool has_opCmp() const noexcept
inline auto invoke_eq(asIScriptContext *ctx, const void *lhs, const void *rhs) const -> script_invoke_result<bool>
inline auto invoke_compare(asIScriptContext *ctx, const void *lhs, const void *rhs) const -> script_invoke_result<int>
inline std::partial_ordering compare(asIScriptContext *ctx, const void *lhs, const void *rhs) const

Comparing two script objects.

Parameters:
  • ctx – Script context

  • lhs – Left object

  • rhs – Right object

Returns:

std::partial_ordering Object relationship, or partial_ordering::unordered when error occurred.

inline bool eq(asIScriptContext *ctx, const void *lhs, const void *rhs) const
inline explicit operator bool() const noexcept
class get_comparator_result

Public Types

using error_type = status::error_type

Public Functions

get_comparator_result() = delete
get_comparator_result(const get_comparator_result&) = default
~get_comparator_result() = default
get_comparator_result &operator=(const get_comparator_result&) = default
inline status get_status() const noexcept
inline script_element_comparator get() const
inline explicit operator bool() const noexcept
inline explicit operator script_element_comparator() const
struct status

Public Types

using error_type = asERetCodes

Public Functions

inline bool good() const noexcept
inline explicit operator bool() const noexcept

Public Members

error_type opEquals = asNO_FUNCTION
error_type opCmp = asNO_FUNCTION
inline get_comparator_result asbind20::container::get_comparator(asITypeInfo *ti)