假设我有两个函数,它们对参数执行完全相同的操作,但使用不同的常量集来执行。对于一个过于简化的例子:
int foo1(int x){
return 3+4*x
}
int foo2(int x){
return 6-4*x
}
在实际的应用程序中,假设有多个参数和常量/文字,当然计算要复杂得多。为了简单性和可维护性,我想将这两个函数重写为一个模板,该模板可以生成这两个函数,这样我就可以调用foo<1>或foo<2>,并生成适当的函数。我知道我可以这样做:
int foo(int x, int funcType){
const int firstConst = (funcType==1) ? 3 : 6;
const int secondConst = (funcType==1) ? 4 : -4;
return firstConst+secondConst*x;
}
但是,由于我总是在编译时知道要使用哪个函数,所以我希望使用模板来避免分支。有办法这样做吗?
发布于 2017-10-11 04:04:40
templatr<int funcType>
void foo(int x){
const int firstConst = (funcType==1) ? 3 : 6;
const int secondConst = (funcType==1) ? 4 : -4;
return firstConst+secondConst*x;
}
在任何非零优化设置下,任何值得使用的编译器都不会有上述模板函数的运行时分支。
而且它通常比特征类更容易阅读。
一般情况下,您可以通过编写长分支代码来获得这种技术的乐趣,这些代码可以编译成紧凑的操作。如果您的代码很好地分解成几个部分(比如bool do_foo
作为模板参数),那么这种扩展是相当好的。
超出此范围,您可能希望避免维护数字ID的中心列表。通过标记分派到一个启用了constexpr函数的constexpr,或者将一个模板非类型指针传递给constexpr struct来查找特征,两者都可以通过分布式函数子类型声明为您提供零开销效果。
最后,您可以直接通过一个属性类:
template<class Traits>
void foo(int x){
return x*Traits::z+Traits::y;
}
或
template<class Traits>
void foo(int x){
return x*Traits{}.z+Traits{}.y;
}
甚至是
template<class Traits>
void foo(int x, Traits traits={}){
return x*traits.z+traits.y;
}
视具体需要而定。
发布于 2017-10-11 03:58:10
您可以使用属性类模板分别管理常量/文本。
template <int FuncType>
struct Constants;
template <>
struct Constants<1> {
static const int firstConst = 3;
static const int secondConst = 4;
};
template <>
struct Constants<2> {
static const int firstConst = 6;
static const int secondConst = -4;
};
template <int FuncType>
int foo(int x){
return Constants<FuncType>::firstConst + Constants<FuncType>::secondConst * x;
}
那就叫它
foo<1>(42);
foo<2>(42);
发布于 2017-10-11 08:04:04
类似于特性案例,您可以这样做:
template <int a, int b>
int foo(int x)
{
return a * x + b;
}
int foo1(int x){
return foo<4, 3>(x);
}
int foo2(int x){
return foo<-4, 6>(x);
}
https://stackoverflow.com/questions/46679494
复制相似问题