在实时计算中,有时会有一个速率组的概念。这本质上是调用给定函数的频率。(例如,RG 10 可能意味着每 10 毫秒执行一次)。
我想知道是否有一种很好的方法C++通过模板魔术对此属性进行编码,如下所示:
template<int rate_group> void integrate( float& some_integral, float spot_value );
上述函数可以实例化如下:
while(true) // outer control loop
{
// do something
integrate<10>( error_sum, sense_feedback );
for( int i = 0 ; i < 10 ; i++) // inner control loop
{
integrate<1>( error_sum_2, some_other_sense );
// sleep 1ms
}
}
以上是一个玩具场景,我只是在探索是否有现有的成语来做这种事情。我认为我想从这样的模板化方法中获得的最重要的属性是属性传递性:任何具有速率组rate_group
的函数都会自动(在编译时)解析为它调用的正确专用子例程。(例如,从内部调用integrate<10>()
到其他模板化函数将自动使用正确的速率组)。
编辑:这是对一些所需属性的更充实的描述。
- 可能最大的功能是设计时编译器警告。假设一个特定的函数
foo
不允许在快速速率组中,我想确保我调用的任何顶级函数树永远不会调用foo<10>
但允许调用foo<100>
。以上确实需要有一种机制来按上下文实例化模板。例如,带有template<int rate_group>
的函数将自动实例化它与费率组调用的任何函数。
例子:
template<int rate_group> void foo( /* ... */ );
template<int rate_group> void bar( /* ... */ );
template<int rate_group> void baz( /* ... */ );
/* impl */
void foo<10>( /* ... */ ){ std::static_assert(false, "this method cannot be called at this rate group"); };
template<int rate_group> void bar( /* ... */ )
{
// do stuff
foo();
}
使用bar<100>
应该可以正常工作,但尝试构建bar<10>
应该会导致编译时断言。
上述功能发挥作用的关键是能够为任何C++块提供上下文速率组属性,并默认将其传递给该块内进行的任何调用。
建立在 #1 之上,模板将具有费率组的顺序,以禁止使用比自身费率组慢的函数:
void foo<50>( /* ... */ ) { bar<10>(); // OK - this is a higher rate group, and would be allowed bar<50>(); // OK - same rate-group bar<100>(); // NO - this could be a slow function - fail compilation }
仅这两个功能就已经有很长的路要走。但是,两者都取决于财产的自动维护。我不确定C++允许这种级别的元编码。
我不知道你的问题的成语,但你确实可以使用模板来处理这个问题。
根据您的限制:
- 内部函数不应调用更大的速率。
- 可以在给定范围内限制功能
我会选择模板类
template <std::size_t N>
class RateGroup
{
friend int main(int, char**); // Give only one entry point
// to create main rates.
Rate() = default;
public:
Rate(const& Rate) = default;
template <std::size_t N2>
RateGroup<N2> New() const requires (N2 <= N) { return {}; }
// Or SFINAE or static_assert instead of C++20 requires.
};
那么你的功能可能是
template<std::size_t N>
void foo(RateGroup<N> /* ... */ ) requires (N > 10);
template<std::size_t N> void bar(RateGroup<N> rateGroup, /* ... */ )
{
// ...
foo(rateGroup /*, ...*/);
}
inline void baz(RateGroup<50> rateGroup /*, ... */ )
{
bar(rateGroup); // Same one, so 50.
bar(rateGroup.New<10>()); // OK, 10 < 50.
bar(rateGroup.New<100>()); // Fail to compile as expected, !(100 < 50).
bar(RateGroup<100>()); // Fail to compile: constructor is restricted to allowed functions
}
因此,您可以为函数设置固定的RateGroup
或模板化函数。