【发布时间】:2015-10-21 06:10:35
【问题描述】:
#include <iostream>
template <typename T>
struct node {
T value;
node const* prev;
constexpr node(const T& value, node const* prev = nullptr)
: value{value}, prev{prev} {}
constexpr node push_front(const T& value) const {
return node(value, this);
}
};
struct Something {
node<int> n;
constexpr Something(const int i) : n{node<int>(i)} {}
constexpr Something(const node<int>& n) : n{n} {}
};
constexpr void print(const Something& s) {
bool first = true;
for (const node<int>* i = &s.n; i != nullptr; i = i->prev) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << i->value;
}
}
constexpr Something recursive_case(Something& s, const unsigned int i) {
Something result(s.n.push_front(i % 10));
auto j = i / 10;
return j != 0 ? recursive_case(result, j) : result;
}
constexpr Something base_case(const unsigned int i) {
Something result(i % 10);
auto j = i / 10;
return j != 0 ? recursive_case(result, j) : result;
}
int main() { print(base_case(21)); }
我有一个像上面所示的递归函数(base_case 和recursive_case)。我从这个链接中得到了node 对象的想法:https://gist.github.com/dabrahams/1457531#file-constexpr_demo-cpp-L66,然后我对其进行了修改以满足我的需要。我上面的问题是我遇到了分段错误。
谢谢。
编辑:
-
很抱歉没有早点尝试调试器。这是输出:
$ lldb ./ww ~/scratch/ww (lldb) target create "./ww" Current executable set to './ww' (x86_64). (lldb) run Process 32909 launched: './ww' (x86_64) Process 32909 stopped * thread #1: tid = 0x4d4e8e, 0x000000010000109b ww`print(s=0x00007fff5fbfec80) + 91 at ww.cpp:32, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000000010000109b ww`print(s=0x00007fff5fbfec80) + 91 at ww.cpp:32 29 } else { 30 std::cout << ", "; 31 } -> 32 std::cout << i->value; 33 } 34 } 35 (lldb)我会尝试使用
new或智能指针,但根据我的阅读,它们不能在constexpr函数中使用。 -
我尝试同时使用
new和智能指针。-
对于
new,我收到此错误:ww.cpp:19:15: error: constexpr constructor never produces a constant expression [-Winvalid-constexpr] constexpr Something(const int i) : n{new node<int>(i)} {} ^ ww.cpp:19:42: note: subexpression not valid in a constant expression constexpr Something(const int i) : n{new node<int>(i)} {} ^ -
对于
unique_ptr,我收到此错误:ww.cpp:26:11: note: non-constexpr constructor 'unique_ptr' cannot be used in a constant expression : n{std::unique_ptr<node<int>, deleter<node<int>>>(new node<int>(i))} {}
-
我研究了一些,我认为可以使用 C++ 模板解决这个问题。我只需要一种方法来捕获递归的中间结果,例如某种编译时列表,然后颠倒顺序。
【问题讨论】:
-
如果您遇到崩溃,您应该在调试器中运行以捕获崩溃,并查看它在您的代码中发生的位置。至少,请编辑您的问题,在代码中包含崩溃的位置,以及所涉及的不同变量的值。
-
删除所有的
constexpr,你应该可以使用调试器单步执行,看看哪里出了问题。递归看起来是有限的,所以我的钱在i != nullptr上。跨度> -
我认为这个算法不能正确地用于构建 constexp 函数。有关详细信息,请参阅我编辑的答案。
标签: templates recursion c++14 template-meta-programming constexpr