Given I have N parameters of different types (uint, int and float) and each parameter has its own valid range of values (i.e. from 2.5 to 20.0). Given also that some parameters are derived from other parameters. For those parameters I use different functions (f1, f2, f3, ...).
To be able to calculate the valid range of values (minimum and maximum) of the derived parameters, I have defined for each derived parameter two new functions f_min and f_max. Inside those functions I call f with the right combination of min and max parameters values to get the limit bounds of my derived parameter.
Let's make a simple example:
f(a, b) = a / b
min = f(a_min, b_max)
max = f(a_max, b_min)
First, I store all minimum and maximum parameters values into two containers. Then I define a deriveLimit
template function wich gets as template arguments a pointer to the function to use to derive the limit and the list of parameter indexes that it depends on. As function arguments the deriveLimit
template functions gets the two list of min and max parameter values.
template <ParamIndex ...Indexes, typename ParamType, typename ...Args>
static ParamData deriveLimitUtil(const ParamData minParams[], const ParamData maxParams[],
ParamValue<ParamType> (*function)(ParamValue<Args>...))
{
ParamValue<ParamType> result = function(ParamValue<Args>(minParams[Indexes])..., ParamValue<Args>(maxParams[Indexes])...);
return result.getData();
}
template <typename FuncType, FuncType function, ParamIndex ...Indexes>
static ParamData deriveLimit(const ParamData minParams[], const ParamData maxParams[])
{
return deriveLimitUtil<Indexes...>(minParams, maxParams, function);
}
For example to derive the upper limit of parameter 2, I call deriveLimit
as follow:
deriveLimit<typeof(&DeriveTest::deriveMaxLimit2), &DeriveTest::deriveMaxLimit2, ParamIndex::PARAM_2_INT, ParamIndex::PARAM_3_FLOAT_1>(minParams, maxParams);
Where deriveMaxLimit2 is declared as follow:
ParamValue<int32_t> DeriveTest::deriveMaxLimit2(ParamValue<int32_t> minValue2, ParamValue<float> minValue3, ParamValue<int32_t> maxValue2, ParamValue<float> maxValue3)
When I compile this code, the compiler returns the following error:
error: mismatched argument pack lengths while expanding ‘(ParamValue<Args>)(maxParams[Indexes])’
In instantiation of ParamData deriveLimitUtil(const ParamData*, const ParamData*, ParamValue<ParamType> (*)(ParamValue<Args>...)) [with short unsigned int ...Indexes = {1u, 2u}; ParamType = int; Args = {int, float, int, float}]’:
required from ParamData deriveLimit(const ParamData*, const ParamData*) [with FuncType = ParamValue<int> (*)(ParamValue<int>, ParamValue<float>, ParamValue<int>, ParamValue<float>); FuncType function = DeriveTest::deriveMaxLimit2; short unsigned int ...Indexes = {1u, 2u}]’
How to I expand only half of the parameter pack Args for ParamValue<Args>(minParams[Indexes])...
?
Parameter packs can only be expanded in a strictly-defined list of contexts, and operator , is not one of them. In other words, it's not possible to use pack expansion to generate an expression consisting of a series of subexpressions delimited by operator , .
[edit] A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments. A template with at least one parameter pack is called a variadic template.
How to I expand only half of the parameter pack
Args
forParamValue<Args>(minParams[Indexes])...
?
#include <tuple>
#include <utility>
#include <cstddef>
template <ParamIndex ...Indexes, typename ParamType, typename ...Args, std::size_t ...Is>
static ParamData deriveLimitUtil(const ParamData minParams[], const ParamData maxParams[],
ParamValue<ParamType> (*function)(ParamValue<Args>...),
std::index_sequence<Is...>)
{
using Tuple = std::tuple<Args...>;
ParamValue<ParamType> result = function(ParamValue<std::tuple_element_t<Is, Tuple>>(minParams[Indexes])...
, ParamValue<std::tuple_element_t<Is, Tuple>>(maxParams[Indexes])...);
return result.getData();
}
template <typename FuncType, FuncType function, ParamIndex ...Indexes>
static ParamData deriveLimit(const ParamData minParams[], const ParamData maxParams[])
{
return deriveLimitUtil<Indexes...>(minParams, maxParams, function, std::make_index_sequence<sizeof...(Indexes)>{});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With