2
\$\begingroup\$

For the following Julia code:

mutable struct MutationWeights
    mutate_constant::Float64
    optimize::Float64
end

const mutations = [fieldnames(MutationWeights)...]

@generated function MutationWeights(;
    mutate_constant=0.048,
    optimize=0.0,
)
    return :(MutationWeights($(mutations...)))
end

"""Convert MutationWeights to a vector."""
@generated function Base.convert(
    ::Type{Vector}, weightings::MutationWeights
)::Vector{Float64}
    fields = [:(weightings.$(mut)) for mut in mutations]
    return :([$(fields...)])
end

I wrote the following C++ alternative:

struct MutationWeights {
    float mutate_constant = 0.048;
    float optimize = 0.0;
};

const auto mutations = std::vector<std::string>{"mutate_constant", "optimize"};

template <typename... Args>
MutationWeights createMutationWeights(Args&&... args) {
    return {std::forward<Args>(args)...};
}

std::vector<double> convertMutationWeightsToVector(const MutationWeights& weightings) {
    return {weightings.mutate_constant,
            weightings.optimize};
}

Is this the most sensible way of doing it, or would you suggest something different?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Hope my edit describes what your code is doing. \$\endgroup\$
    – convert
    Jun 25 at 16:13

1 Answer 1

6
\$\begingroup\$

Precision

float is usually a 32-bit floating point type. Perhaps you meant double? With C++23, you can use std::float64_t.

Aggregates

There is aggregate initialization that removes the need for createMutationWeights. Note that if narrowing conversion should be allowed, then createMutationWeights does not help with it.

(Implicit) conversion functions

If the conversion into std::vector<double> is often needed, I would implement a conversion function and make it explicit (will require a cast like static_cast to be used) if needed.

struct MutationWeights {
    float mutate_constant = 0.048;
    float optimize = 0.0;

    operator std::vector<double>() {
        return { mutate_constant, optimize };    
    }
};

Reconsider the interface

I would recommend returning std::span<float> or even std::span<float, 2> (i.e. statically sized). One could also try std::array<float, 2> to avoid some lifetime issues.

\$\endgroup\$
2
  • \$\begingroup\$ Not that important but maybe you want to remove weightings from your vector implementation. \$\endgroup\$
    – dearn44
    Jun 24 at 17:57
  • \$\begingroup\$ @dearn44, thanks, fixed now. \$\endgroup\$ Jun 25 at 0:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.