c++ lambda 函數的 static 屬性是否無效?
嘗試用 c++ 實現 Y Combinator 時發現一個奇怪的情況,代碼如下
#include &
#include &
#include &
using namespace std;
int main()
{
auto F = [](auto f, int n)-&>int {if (n &< 1) return 1; else return n * f(n - 1); }; auto H = [](auto f, int n)-&>int {if (n &< 1) return 1; else return n + f(n - 1); }; auto Y = [](autof) { static auto fgen = [](auto self, int n)-&>int // 使用 static 的目的是避免棧解除後 fgen 引用錯誤,雖然實際上並不會出錯
{
return f([](int k)-&>int {return self(self, k); }, n);
};
return [](int k){return fgen(fgen, k);};
};cout &<&< Y(F)(3) &<&< endl &<&< Y(H)(5); return 0; }
期望輸出6和120,實際上輸出的是6和16。
接下來我做了如下改動
auto Y = [](autof, int n)
{
static auto fgen = [](auto self, int n)-&>int
{
return f([](int k)-&>int {return self(self, k); }, n);
};
return fgen(fgen, n);
};cout &<&< Y(F, 3) &<&< endl &<&< Y(H, 5);
依舊輸出6和16。
考慮到是不是 lambda 函數的特殊性,我又用可變參數模板試了下:
#include &
#include &
#include &
#include &
using namespace std;
template&
auto Y(FN f, ARGS... args) // 這個居然能匹配,很奇怪
{
static auto fgen = [](auto self, ARGS... args)-&>int
{
return f([](int k)-&>int {return self(self, k); }, args...);
};
return fgen(fgen, args...);
}
int main()
{
auto F = [](auto f, int n)-&>int {if (n &< 1) return 1; else return n * f(n - 1); }; auto H = [](auto f, int n)-&>int {if (n &< 1) return 1; else return n + f(n - 1); }; cout &<&< Y(F, 3) &<&< endl &<&< Y(H, 5); cout &<&< endl &<&< (typeid(F) == typeid(H)); return 0; }輸出
6
16
0這沒什麼說服力,畢竟F 和 H 類型並不一樣。但二者都是右值,看來是調用時生成的。
所以,lambda 函數內的 static 屬性是都沒有意義嗎?
正確答案:因為參數是auto,所以Y是一個模板函數,你傳入F和傳入H的時候分別特化了兩個版本,當然也就有兩個static fgen了。這沒有什麼奇怪的。
auto H = [](auto f, int n)-&>int {if (n &< 1) return 1; else return n + f(n - 1); };
你這個H看上去不是階乘而是sum啊
Y是表達式
自己回答一下。搞了這麼個玩意兒。
#include &
#include &
#include &
#include &
#include &
using namespace std;
template&
auto YTmpl(FN f, ARGS... args)
{
static auto fgen = [](auto self, ARGS... args)-&>int
{
return f([](int k)-&>int {return self(self, k); }, args...);
};
return fgen(fgen, args...);
}
auto YLambda = [](autof, int n)
{
static auto fgen = [](auto self, int n)-&>int
{
return f([](int k)-&>int {return self(self, k); }, n);
};
return fgen(fgen, n);
};
#define YY(fn, ...)
YTmpl(decltype(test::Decode(test::decVal&
#define YYY(fn, ...)
YLambda(decltype(test::Decode(test::decVal&
namespace test {
template&
struct decode
{
typedef function&
};
template&
decode&
{
decode&
return dec;
}
template&
RET decVal() { RET val; return val; }
}
int main()
{
auto F = [](auto f, int n)-&>int {if (n &< 1) return 1; else return n * f(n - 1); };
auto H = [](auto f, int n)-&>int {if (n &< 1) return 1; else return n + f(n - 1); };
cout &<&< YY(F, 3) &<&< endl &<&< YY(H, 5) &<&< endl;
cout &<&< YYY(H, 5) &<&< endl &<&< YYY(F, 3);
return 0;
}
輸出結果
7
16
1206
還是實例化的問題,怨不得 lambda。
推薦閱讀:
※哪些函數的增長速度能勝過指數函數?
※如何理解logistic函數?
※你見過的最污的函數圖像是什麼?
※大家都用什麼軟體繪製函數圖像呢?
※這個推導是正確的嗎?為什麼