我有一些goto負載的 C 代碼,看起來像
#include <stdlib.h>
void test0()
{
int i = 0;
loop:
i ;
if (i > 10) goto done;
goto loop;
done:
exit(EXIT_SUCCESS);
}
我想擺脫gotos 而(主要)保留原始代碼的外觀;更多或多或少的規則出來for,while等(除非他們背后的宏隱藏),作為太多改變現有代碼的外觀。想象一下,想要最小化現有代碼和更改代碼之間的“差異”。
一個想法是使用帶有方法的類:
class test1 final
{
int i = 0;
void goto_loop()
{
i ;
if (i > 10) goto_done();
goto_loop();
}
void goto_done()
{
exit(EXIT_SUCCESS);
}
public:
test1() { goto_loop(); }
};
這可行,但每次呼叫都會goto_loop()添加到呼叫堆疊中。有什么方法可以進行exec類似的函式呼叫嗎?也就是說,以某種方式呼叫“行內”函式......執行附加代碼而不添加到呼叫堆疊?有沒有辦法使尾遞回顯式?
使用 C 20(甚至 C 23)是可以接受的,盡管 C 17 解決方案會“不錯”。
對于所有想知道“為什么”的人 在真正的原代碼是基本...
uj5u.com熱心網友回復:
聽起來您想確保尾呼叫優化。目前沒有標準的方法來做到這一點,但如果你使用 Clang,你可以使用該clang::musttail屬性。
uj5u.com熱心網友回復:
回圈可能會保留代碼結構:
void test2()
{
int i = 0;
for (;;) {
i ;
if (i > 10) break;
continue;
}
exit(EXIT_SUCCESS);
}
即使
void test3()
{
for (int i = 0; i < 11; i) {
/*Empty*/
}
exit(EXIT_SUCCESS);
}
會更慣用(假設一些有用的代碼,因為回圈實際上是無用的)。
uj5u.com熱心網友回復:
我的解決方案是撰寫一個exec()停止遞回的例程:
template<typename Func>
void exec(const Func& f)
{
using function_t = Func;
static std::map<const function_t*, size_t> functions;
const auto it = functions.find(&f);
if (it == functions.end())
{
functions[&f] = 1;
while (functions[&f] > 0)
{
f();
functions[&f]--;
}
functions.erase(&f);
}
else
{
functions[&f] ;
}
}
使用該實用程式,我可以或多或少地保留現有代碼的外觀
class test4 final
{
int i = 0;
void goto_loop_() {
i ;
if (i > 10) goto_done(); }
void goto_loop() { goto_loop_(); static const auto f = [&]() { goto_loop(); }; exec(f); }
void goto_done()
{
exit(EXIT_SUCCESS);
}
public:
test4() { goto_loop(); }
};
(使用 lambda 避免了指向成員函式的麻煩。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/405885.html
標籤:
上一篇:遞回物件的遞回搜索
