[英]C++ Expand only part of the parameter pack
Given I have N parameters of different types (uint, int and float) and each parameter has its own valid range of values (ie from 2.5 to 20.0). 鉴于我有不同类型的N个参数(uint,int和float),并且每个参数都有自己的有效值范围(即从2.5到20.0)。 Given also that some parameters are derived from other parameters.
还给出了一些参数来自其他参数。 For those parameters I use different functions (f1, f2, f3, ...).
对于那些参数,我使用不同的函数(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. 为了能够计算派生参数的有效值范围(最小值和最大值),我为每个派生参数定义了两个新函数f_min和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.
在这些函数中,我使用min和max参数值的正确组合调用f来获取派生参数的限制边界。
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. 然后我定义一个
deriveLimit
模板函数,它获取模板参数作为指向函数的指针,该函数用于派生限制以及它所依赖的参数索引列表。 As function arguments the deriveLimit
template functions gets the two list of min and max parameter values. 作为函数参数,
deriveLimit
模板函数获取最小和最大参数值的两个列表。
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: 例如,为了得到参数2的上限,我调用
deriveLimit
如下:
deriveLimit<typeof(&DeriveTest::deriveMaxLimit2), &DeriveTest::deriveMaxLimit2, ParamIndex::PARAM_2_INT, ParamIndex::PARAM_3_FLOAT_1>(minParams, maxParams);
Where deriveMaxLimit2 is declared as follow: 其中deriveMaxLimit2声明如下:
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])...
? 如何扩展
ParamValue<Args>(minParams[Indexes])...
的参数包Args的一半ParamValue<Args>(minParams[Indexes])...
?
How to I expand only half of the parameter pack
Args
forParamValue<Args>(minParams[Indexes])...
?如何扩展
ParamValue<Args>(minParams[Indexes])...
的参数包Args
一半ParamValue<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)>{});
}
The solution is much simple as I initially thought. 正如我最初想的那样,解决方案非常简单。 I define a new template class ParamLimit which represents the limits of a parameter.
我定义了一个新的模板类ParamLimit,它表示参数的限制。 Now, instead to pass the
deriveLimit
functions the two list of minimum and maximum parameter values, I pass a list of ParamLimit
. 现在,我传递一个
ParamLimit
列表,而不是传递deriveLimit
函数的两个最小和最大参数值列表。
class ParamLimit
{
public:
constexpr ParamLimit(RawValue min, RawValue max) : m_min(min), m_max(max) {}
template <typename T>
T getLowerLimit() const { return RawValueAccessor<T>::getValue(m_min); }
template <typename T>
T getUpperLimit() const { return RawValueAccessor<T>::getValue(m_max); }
private:
RawValue m_min;
RawValue m_max;
};
template <typename T>
class ParamLimitValue
{
public:
constexpr ParamLimitValue(T min, T max) : m_data(min, max) {}
explicit ParamLimitValue(const ParamLimit& data) : m_data(data) {}
T getLowerLimit() const { return m_data.getLowerLimit<T>(); }
T getUpperLimit() const { return m_data.getUpperLimit<T>(); }
private:
ParamLimit m_data;
};
Then the code looks like that: 然后代码看起来像这样:
template <ParamIndex ...Indexes, typename ParamType, typename ...Args>
static ParamData deriveLimitUtil(const ParamLimit paramLimits[],
ParamValue<ParamType> (*function)(ParamLimitValue<Args>...))
{
ParamValue<ParamType> result = function(ParamLimitValue<Args>(paramLimits[Indexes])...);
return result.getData();
}
template <typename FuncType, FuncType function, ParamIndex ...Indexes>
static ParamData deriveLimit(const ParamLimit paramLimits[])
{
return deriveLimitUtil<Indexes...>(paramLimits, function);
}
And the derivation function: 和派生功能:
static ParamValue<int32_t> deriveMaxLimit2(ParamLimitValue<int32_t> param2, ParamLimitValue<float> param3);
By doing like that, the size of Args matches with the size of Indexes and the code stays easy to read and maintainable. 通过这样做,Args的大小与索引的大小匹配,并且代码易于阅读和维护。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.