在C++11中,我需要从0,...,n递归调用一个函数(其中n是一个编译时间常数)。这就是问题的结构,它似乎有致命的缺陷:
#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>());
}以及完整的错误消息:
/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
}我的理解是,在最后一行x * eval(c, x, Int<d>(), Int<i + 1>());中,当i+1 = n时,将选择返回1的第一个函数,但是编译器说调用是不明确的。谁能解释一下原因吗?以及如何解决这个问题?
注意:我知道您不能部分地专门化一个模板函数。我试图模仿行为,而不是过载。
编辑
问题似乎在于C::SizeAtCompileTime的扩大。当我对这个常量进行硬编码时,程序会编译.是否有一个通用的C++规则来说明为什么会发生这种情况?或者这是特征特定的东西?
发布于 2018-05-08 12:57:47
歧义的原因,在一条腿上,是因为您有两个函数模板,它们就偏序而言是一样好的。当第一个重载的模板参数不是依赖值(原始问题中的n)时,偏序可以很好地决定它。但是C::SizeAtCompileTime是依赖的,因此偏序不再能拯救我们。
不过,我们可以用SFINAE自己解决问题。当i出现冲突时,我们所需要做的就是从重载集中删除第二个重载。这可以用一个简单的std::enable_if来完成
template<size_t d, typename C, typename X, size_t i>
constexpr auto eval(const C &c, const X &x, const Int<d> &, const Int<i> &)
-> typename std::enable_if<i != C::SizeAtCompileTime - 1 - d, X>::type {
return x * eval(c, x, Int<d>(), Int<i + 1>());
}https://stackoverflow.com/questions/50233314
复制相似问题