在实时计算中,有时存在速率组的概念。这本质上是调用给定函数的频率。 (例如 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++ block 提供上下文速率组属性,并默认将其传递给该 block 内进行的任何调用。
在 #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
或模板化的。
关于c++ - 是否有 C++ 习惯用法通过模板魔法将所谓的速率组(实时计算)编码到函数中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65546386/