假设我有一个向量长度计算函数,它有一个附加inc参数(这告诉相邻元素之间的距离)。一个简单的实现是:
float calcLength(const float *v, int size, int inc) {
float l = 0;
for (int i=0; i<size*inc; i += inc) {
l += v[i]*v[i];
}
return sqrt(l);
}
Run Code Online (Sandbox Code Playgroud)
现在,calcLength可以使用两种inc参数进行调用:何时inc在编译时已知,何时未知。我想要一个calcLength针对常见编译时值inc(如 1)的优化版本。
所以,我会有这样的东西:
template <int C>
struct Constant {
static constexpr int value() {
return C;
}
};
struct Var {
int v;
constexpr Var(int p_v) : v(p_v) { }
constexpr int value() const {
return v;
}
};
template <typename INC>
float calcLength(const float *v, int size, INC inc) {
float l = 0;
for (int i=0; i<size*inc.value(); i += inc.value()) {
l += v[i]*v[i];
}
return sqrt(l);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,可以这样使用:
calcLength(v, size, Constant<1>()); // inc is a compile-time constant 1 here, calcLength can be vectorized
Run Code Online (Sandbox Code Playgroud)
或者
int inc = <some_value>;
calcLength(v, size, Var(inc)); // inc is a non-compile-time constant here, less possibilities of compiler optimization
Run Code Online (Sandbox Code Playgroud)
我的问题是,是否有可能以某种方式保留原始界面,并根据类型(编译时常量与否)自动放入Constant/ ?Varinc
calcLength(v, size, 1); // this should end up calcLength(v, size, Constant<1>());
calcLength(v, size, inc); // this should end up calcLength(v, size, Var(int));
Run Code Online (Sandbox Code Playgroud)
注意:这是一个简单的例子。在我的实际问题中,我有几个函数,例如calcLength,并且它们很大,我不希望编译器内联它们。
注2:我也对不同的方法持开放态度。基本上,我想要一个解决方案,它可以满足这些要求:
1as inc,则实例化一个特殊函数,并且代码很可能被矢量化inc不是编译时常量,则调用通用函数C++ 不提供检测提供的函数参数是否为常量表达式的方法,因此您无法自动区分提供的文字和运行时值。
如果参数必须是函数参数,并且您不愿意在这两种情况下更改它的调用方式,那么您这里唯一的杠杆就是参数的类型:您对Constant<1>()vs的建议Var(inc)非常好看待。