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

95 views Asked by At

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:

  • store all the ratios for a given derived_unit in a container like std::array<T, N> with a fold expression (collection_ratios)
  • store the result of multiply every element in the units member of derived_unit and store it in a variable with a fold expression (ratios_product)

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>;
1

There are 1 answers

6
Not a real meerkat On BEST ANSWER

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;
}