Repository: numpy/numpy
File: numpy/_core/src/multiarray/unique.cpp (C++)

Code before:
    typename T,
    size_t (*hash_func)(const T *, npy_bool),
    int (*equal_func)(const T *, const T *, npy_bool),
    void (*copy_func)(char *, T *)
>
static PyObject*
unique_numeric(PyArrayObject *self, npy_bool equal_nan)
{
    /*
     * Returns a new NumPy array containing the unique values of the input
     * array of numeric (integer or complex).
     * This function uses hashing to identify uniqueness efficiently.
     */

    auto hash = [equal_nan](const T *value) -> size_t {
        return hash_func(value, equal_nan);
    };
    auto equal = [equal_nan](const T *lhs, const T *rhs) -> bool {
        return equal_func(lhs, rhs, equal_nan);
    };

    // Create hashset within the scope of a lambda to allow RAII objects
    // to manage resources.
    using set_type = std::unordered_set<T *, decltype(hash), decltype(equal)>;
    const set_type hashset =
        std::invoke([&]() -> const set_type {
            np::raii::SaveThreadState save_thread_state{};

            // number of elements in the input array
            npy_intp isize = PyArray_SIZE(self);
            set_type hashset(std::min(isize, HASH_TABLE_INITIAL_BUCKETS), hash, equal);
            char *idata = PyArray_BYTES(self);
            npy_intp istride = PyArray_STRIDES(self)[0];
            for (npy_intp i = 0; i < isize; i++, idata += istride) {
                hashset.insert(reinterpret_cast<T *>(idata));
            }
            return hashset;
        });

    npy_intp length = hashset.size();

    PyArrayObject *res_obj = empty_array_like(self, length);
    if (res_obj == NULL) {
        return NULL;
    }

    {
        np::raii::SaveThreadState save_thread_state{};

        char *odata = PyArray_BYTES(res_obj);
        npy_intp ostride = PyArray_STRIDES(res_obj)[0];

Review comment (suggestion):
This seems like a slightly strange use of `std::invoke` to me; [CppCoreGuidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es28-use-lambdas-for-complex-initialization-especially-of-const-variables) suggest that `()` alone is fine (though do not mention `std::invoke` here).

Code after:
    typename T,
    size_t (*hash_func)(const T *, npy_bool),
    int (*equal_func)(const T *, const T *, npy_bool),
    void (*copy_func)(char *, T *)
>
static PyObject*
unique_numeric(PyArrayObject *self, npy_bool equal_nan)
{
    /*
     * Returns a new NumPy array containing the unique values of the input
     * array of numeric (integer or complex).
     * This function uses hashing to identify uniqueness efficiently.
     */

    auto hash = [equal_nan](const T *value) -> size_t {
        return hash_func(value, equal_nan);
    };
    auto equal = [equal_nan](const T *lhs, const T *rhs) -> bool {
        return equal_func(lhs, rhs, equal_nan);
    };

    using set_type = std::unordered_set<T *, decltype(hash), decltype(equal)>;

    // number of elements in the input array
    npy_intp isize = PyArray_SIZE(self);
    set_type hashset(std::min(isize, HASH_TABLE_INITIAL_BUCKETS), hash, equal);

    {
        np::raii::SaveThreadState save_thread_state{};

        char *idata = PyArray_BYTES(self);
        npy_intp istride = PyArray_STRIDES(self)[0];
        for (npy_intp i = 0; i < isize; i++, idata += istride) {
            hashset.insert(reinterpret_cast<T *>(idata));
        }
    }

    PyArrayObject *res_obj = empty_array_like(self, hashset.size());
    if (res_obj == NULL) {
        return NULL;
    }

    {
        np::raii::SaveThreadState save_thread_state{};

        char *odata = PyArray_BYTES(res_obj);
        npy_intp ostride = PyArray_STRIDES(res_obj)[0];
        for (auto it = hashset.begin(); it != hashset.end(); it++, odata += ostride) {
            copy_func(odata, *it);
        }
    }