Suppose that I have a vector length calculation function, which has an additional inc parameter (this tells the distance between neighboring elements). A simple implementation would be:
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);
}
Now, calcLength can be called with two kind of inc parameters: when inc is known at compile-time, and when it is not. I'd like to have an optimized calcLength version for common compile-time values of inc (like 1).
So, I'd have something like this:
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);
    }
}
So, this can be used:
calcLength(v, size, Constant<1>()); // inc is a compile-time constant 1 here, calcLength can be vectorized
or
int inc = <some_value>;
calcLength(v, size, Var(inc)); // inc is a non-compile-time constant here, less possibilities of compiler optimization
My question is, would it be possible somehow to keep the original interface, and put Constant/Var in automatically, depending on the type (compile-time constant or not) of inc?
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));
Note: this is a simple example. In my actual problem, I have several functions like calcLength, and they are large, I don't want the compiler to inline them.
Note2: I'm open to different approaches as well. Basically, I'd like to have a solution, which fulfills these:
- the algorithm is specified once (most likely in a template function)
- if I specify 1asinc, a special function instantiated, and the code most likely gets vectorized
- if incis not a compile-time constant, a general function is called
- otherwise (non-1 compile-time constant): doesn't matter which function is called
 
     
     
     
    