I want to compute a lookup table at compile time for a mathematical function in a given range and then retrieve values from the table at run time. My code is as follows:
#include <iostream>
#include <cmath>
template<int size>
class LookupTable {
public:
constexpr LookupTable(double xMin, double xMax) : array(), xMin(xMin), xMax(xMax), dx((xMax - xMin) / (size - 1)) {
for(auto i = 0; i < size; ++i)
array[i] = exp(xMin + i * dx);
}
constexpr double operator()(double x) const {
return array[std::min(std::max(static_cast<int>((x - xMin) / dx), 0), size-1)];
}
private:
double array[size];
double xMin;
double xMax;
double dx;
};
int main() {
const double x = 0.5;
constexpr LookupTable<10000> table(0.0, 1.0);
std::cout << "f(x) = " << table(x) << std::endl; // evaluated at compile time ?
std::cout << "f(x) = " << LookupTable<10000>(0.0, 1.0)(x) << std::endl; // evaluated at run time ?
return 0;
}
The code compiles and runs on gcc 5.1 and above but not on Clang 3.8. Clang's error messages are: constexpr variable 'table' must be initialized by a constant expression and non-constexpr function 'exp' cannot be used in a constant expression.
When I remove the constexpr in:
constexpr LookupTable<10000> table(0.0, 1.0);
then the code compiles and runs on Clang as well.
My questions are:
- What is the meaning of the error message "function 'exp' cannot be used in a constant expression" ? And is there a workaround?
- Does that mean that when I declare LookupTable<10000> table(0.0, 1.0); without the constexpr, then the table precomputations happen at run-time? I am using an online compiling tool so I do not have an option to benchmark the code right now.
- I would like to generalize the code and templatize the mathematical function. It works fine with functors but is it possible to use lambdas?
Thanks