我的项目在模板方面有几个尴尬的位置。我知道我的用法略微不标准,但作为基本利益的尴尬(主要是展开一堆循环)。 AKA请不要回答“哦,你不应该使用模板”。所涉及的尴尬在经验上已被证明有超过10倍的加速......
以下模板使用enum class SomeThing : uint8_t
。有一个
template <SomeThing ST>
struct projection_functor {
static constexpr unsigned WIDTH = 640u;/// *** only in
static constexpr unsigned HEIGHT = 480u;/// *** specializations...
void toXYZ(...);
...
};
保证enum class SomeThing
的每个可能值都有专门的版本。此外,非专业版本实际上并不提供WIDTH
和HEIGHT
,只提供专业化(这是我的编译时保证措施)。
我想要做的是使用这些闭包定义一个函数:
template <SomeThing ST>
void forEachXYZ(...params...) {
if(ST == SomeThing::FIRST)
using proj = projection_functor<SomeThing::FIRST>;
else if(ST == SomeThing::SECOND)
using proj = projection_functor<SomeThing::SECOND>;
else
throw std::runtime_error("Unsupported...");
for(unsigned i = 0; i < proj::WIDTH * proj::HEIGHT; ++i) {
// ... setup ...
proj pf;
pf.toXYZ(...);
}
}
这不能编译,但我认为问题proj
在每种情况下都没有正式定义。这是一个非常丑陋但功能性的解决方案,我想保留在forEachXYZ
:
#define THIS_UGLY_MACRO() \
for(unsigned int i = 0; n < proj::WIDTH * proj::HEIGHT; ++i) { \
/* ... setup ... */ \
proj pf; \
pf.toXYZ(...); \
}
现在我可以打电话了
template <SomeThing ST>
void forEachXYZ(...params...) {
if(ST == SomeThing::FIRST) {
using proj = projection_functor<SomeThing::FIRST>;
THIS_UGLY_MACRO();
}
else if(ST == SomeThing::SECOND) {
using proj = projection_functor<SomeThing::SECOND>;
THIS_UGLY_MACRO();
}
else
throw std::runtime_error("Unsupported...");
}
这显然有效,因为它的范围是从模板参数比较中评估的if
语句。
这是唯一的解决方案,还是有更好的方法可以根据模板参数告知循环proj
实际是什么?
我认为编写一个辅助函数可以完成,但这更高级别“我能以这种方式实际使用模板做什么”这个问题。
感谢您的任何建议:)
答案 0 :(得分:1)
您可以定义模板而不是宏:
template <class Projection>
void projectXYZ(...params...) {
for(unsigned int i = 0; n < proj::WIDTH * proj::HEIGHT; ++i) {
/* ... setup ... */
Projection pf;
pf.toXYZ(...);
}
}
然后叫它:
template <SomeThing ST>
void forEachXYZ(...params...) {
if(ST == SomeThing::FIRST) {
projectXYZ<projection_functor<SomeThing::FIRST>>(std::move(param), ...);
}
else if(ST == SomeThing::SECOND) {
projectXYZ<projection_functor<SomeThing::SECOND>>(std::move(param), ...);
}
else {
throw std::runtime_error("Unsupported...");
}
}