c++variadic-templatesfold-expression

Accessing indiviual alias inside another alias that is a parameter pack with a fold expression


Given this types:

template<Ratio r, Symbol s>
struct base_unit {
    using ratio = r;
    using symbol = s;
};

template <BaseUnit... baseUnits>
struct derived_unit {
    using units = std::tuple<baseUnits...>;
};

If, for example, I have a type like:

template <typename T>
struct Computations {
    using collection_ratios = /* */
    static constexpr ratios_product = /* */
}

I wanted to know how can I:

Edit:

Where T is a specialization of derived_unit, like, for example:

struct MetersPerSecond :
   public speed,
   public derived_unit<         
        base_unit<Kilo, m>,
        base_unit<Root, s>
   >
{};

Edit 2:

template <typename T>
concept RatioV = (std::is_integral_v<T> || std::is_floating_point_v<T>)
    && !std::is_same_v<T, char>;


consteval double getFactor(double base, double exponent);

template <RatioV T = short, T Base = 10, T Exponent = 0>
struct ratio {
    static constexpr T base = Base;
    static constexpr T exponent = Exponent;
    static constexpr T value = getFactor(base, exponent);
};

consteval double getFactor(double base, double exponent) {
    double result = 1;
    for (int i = 0; i < exponent; i++)
        result *= base;
    return result;
}

using Yocto = ratio<short, 10, -24>;
using Zepto = ratio<short, 10, -21>;
using Atto = ratio<short, 10, -18>;
using Femto = ratio<short, 10, -15>;
using Pico = ratio<short, 10, -12>;
using Nano = ratio<short, 10, -9>;
using Micro = ratio<short, 10, -6>;
using Milli = ratio<short, 10, -3>;
using Centi = ratio<short, 10, -2>;
using Deci = ratio<short, 10, -1>;
using Root = ratio<short, 10, 0>;
using Deca = ratio<short, 10, 1>;
using Hecto = ratio<short, 10, 2>;
using Kilo = ratio<short, 10, 3>;
using Mega = ratio<short, 10, 6>;
using Giga = ratio<short, 10, 9>;
using Tera = ratio<short, 10, 12>;
using Peta = ratio<short, 10, 15>;
using Exa = ratio<short, 10, 18>;
using Zetta = ratio<short, 10, 21>;
using Yotta = ratio<short, 10, 24>;

Solution

  • Is this what you are looking for?

    All it does is get the list of ratio types into collection_ratios. And using that list, multiples all of the static value's into ratios_product.

    template<typename Tuple>
    struct ratios;
    
    template<typename... Ts>
    struct ratios<std::tuple<Ts...>> {
        using type = std::tuple<typename Ts::ratio...>;
    };
    
    template <typename Tuple>
    struct ratios_product_impl;
    
    template<typename... Ts>
    struct ratios_product_impl<std::tuple<Ts...>>
    {
        static constexpr auto value = (1 * ... * Ts::value);
    };
    
    template <typename T>
    struct Computations {
        using collection_ratios = typename ratios<typename T::units>::type;
    
        // Calculates the product of all ratio values.
        static constexpr auto ratios_product = ratios_product_impl<collection_ratios>::value;
    };
    
    #include <iostream>
    
    int main() {
        Computations<MetersPerSecond> c;
        std::cout << c.ratios_product; // Prints 10000 for MetersPerSecond.
        return 0;
    }