In C++11, I need to call a function recursively from 0,...,n
(where n
is a compile time constant). This is the structure of the problem, which appears to be fatally flawed:
#include "Eigen/Dense"
template<size_t i>
struct Int {
};
template<size_t d, typename C, typename X>
constexpr X eval(const C &c, const X &x, const Int<d> &, const Int<C::SizeAtCompileTime - 1 - d> &) {
return 1;
}
template<size_t d, typename C, typename X, size_t i>
constexpr X eval(const C &c, const X &x, const Int<d> &, const Int<i> &) {
return x * eval(c, x, Int<d>(), Int<i + 1>());
}
int main() {
const size_t d = 1;
const Eigen::Matrix<double, 1, 7> c = Eigen::Matrix<double,1,7>::Zero();
const double x = 5;
eval(c, x, Int<d>(), Int<0>());
}
and the full error message:
/usr/bin/cmake --build /mnt/c/Dropbox/clion/recursion/cmake-build-debug --target recursion -- -j 4
Scanning dependencies of target recursion
[ 50%] Building CXX object CMakeFiles/recursion.dir/main.cpp.o
/mnt/c/Dropbox/clion/recursion/main.cpp: In instantiation of 'constexpr X eval(const C&, const X&, const Int<d>&, const Int<i>&) [with long unsigned int d = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double; long unsigned int i = 4ul]':
/mnt/c/Dropbox/clion/recursion/main.cpp:14:20: recursively required from 'constexpr X eval(const C&, const X&, const Int<d>&, const Int<i>&) [with long unsigned int d = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double; long unsigned int i = 1ul]'
/mnt/c/Dropbox/clion/recursion/main.cpp:14:20: required from 'constexpr X eval(const C&, const X&, const Int<d>&, const Int<i>&) [with long unsigned int d = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double; long unsigned int i = 0ul]'
/mnt/c/Dropbox/clion/recursion/main.cpp:21:34: required from here
/mnt/c/Dropbox/clion/recursion/main.cpp:14:20: error: call of overloaded 'eval(const Eigen::Matrix<double, 1, 7>&, const double&, Int<1ul>, Int<5ul>)' is ambiguous
return x * eval(c, x, Int<d>(), Int<i + 1>());
^
/mnt/c/Dropbox/clion/recursion/main.cpp:8:13: note: candidate: constexpr X eval(const C&, const X&, const Int<d>&, const Int<((C:: SizeAtCompileTime - 1) - d)>&) [with long unsigned int d = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double]
constexpr X eval(const C &c, const X &x, const Int<d> &, const Int<C::SizeAtCompileTime - 1 - d> &) {
^
/mnt/c/Dropbox/clion/recursion/main.cpp:13:13: note: candidate: constexpr X eval(const C&, const X&, const Int<d>&, const Int<i>&) [with long unsigned int d = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double; long unsigned int i = 5ul]
constexpr X eval(const C &c, const X &x, const Int<d> &, const Int<i> &) {
^
/mnt/c/Dropbox/clion/recursion/main.cpp:15:1: error: body of constexpr function 'constexpr X eval(const C&, const X&, const Int<d>&, const Int<i>&) [with long unsigned int d = 1ul; C = Eigen::Matrix<double, 1, 7>; X = double; long unsigned int i = 4ul]' not a return-statement
}
My understanding was that in the last line, x * eval(c, x, Int<d>(), Int<i + 1>());
, when i+1 = n
, then the first function which returns 1 would be chosen, but the compiler says that the call is ambiguous. Could somebody explain why? and how to fix this?
Note: I am aware that you cannot partially specialize a template function. I am trying to mimic the behavior instead with overloading.
EDIT
It seems that the issue lies in the expansion of C::SizeAtCompileTime
. When I hard-code that constant, the program compiles. Is there a general C++ rule indicating why that is happening? or is that something that is Eigen specific?
i
increases to 5, both versions satisfy, thus ambiguity. – DemurralC::SizeAtCompileTime
is dependent onC
so it probably counts. Exact rules are gathered here: en.cppreference.com/w/cpp/language/… – Simper