我的意思是:
int main()
{
void a()
{
// code
}
a();
return 0;
}
我的意思是:
int main()
{
void a()
{
// code
}
a();
return 0;
}
当前回答
让我在这里发布一个我认为最干净的c++ 03解决方案
#define DECLARE_LAMBDA(NAME, RETURN_TYPE, FUNCTION) \
struct { RETURN_TYPE operator () FUNCTION } NAME;
...
int main(){
DECLARE_LAMBDA(demoLambda, void, (){ cout<<"I'm a lambda!"<<endl; });
demoLambda();
DECLARE_LAMBDA(plus, int, (int i, int j){
return i+j;
});
cout << "plus(1,2)=" << plus(1,2) << endl;
return 0;
}
(*)在c++世界中使用宏从来不被认为是干净的。
其他回答
局部类已经提到过,但是这里有一种方法可以让它们更像局部函数,使用operator()重载和匿名类:
int main() {
struct {
unsigned int operator() (unsigned int val) const {
return val<=1 ? 1 : val*(*this)(val-1);
}
} fac;
std::cout << fac(5) << '\n';
}
我不建议使用这个,这只是一个有趣的技巧(可以做,但我不应该)。
2014年更新:
随着c++ 11的兴起,你现在可以有一些局部函数,其语法有点像JavaScript:
auto fac = [] (unsigned int val) {
return val*42;
};
对于递归函数,不支持编译时类型演绎:
function<int(int)> factorial{ [&](int n)
{
return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
} };
No.
你想做什么?
处理:
int main(void)
{
struct foo
{
void operator()() { int a = 1; }
};
foo b;
b(); // call the operator()
}
所有这些技巧只是看起来(或多或少)像局部函数,但它们并不是这样工作的。在局部函数中,你可以使用超函数的局部变量。这是一种半全球化。这些把戏都做不到。最接近的是c++0x中的lambda技巧,但它的闭包是在定义时间内绑定的,而不是使用时间。
现代c++ -是的,有lambdas!
在c++的当前版本(c++ 11、c++ 14和c++ 17)中,你可以在函数中使用lambda形式的函数:
int main() {
// This declares a lambda, which can be called just like a function
auto print_message = [](std::string message)
{
std::cout << message << "\n";
};
// Prints "Hello!" 10 times
for(int i = 0; i < 10; i++) {
print_message("Hello!");
}
}
Lambdas还可以通过**引用捕获来修改局部变量。通过引用捕获,lambda可以访问lambda作用域中声明的所有局部变量。可以正常修改和更改。
int main() {
int i = 0;
// Captures i by reference; increments it by one
auto addOne = [&] () {
i++;
};
while(i < 10) {
addOne(); //Add 1 to i
std::cout << i << "\n";
}
}
c++ 98和c++ 03 -不能直接使用,但是可以在局部类中使用静态函数
c++并不直接支持。
也就是说,你可以有局部类,它们可以有函数(非静态或静态),所以你可以在某种程度上得到这个,尽管它有点拼凑:
int main() // it's int, dammit!
{
struct X { // struct's as good as class
static void a()
{
}
};
X::a();
return 0;
}
然而,我对这种做法表示怀疑。每个人都知道(好吧,现在你知道了,反正:))c++不支持局部函数,所以他们习惯了没有它们。然而,他们并不习惯这种拼凑。我在这段代码上花了不少时间,以确保它确实只允许本地函数。不好的。
是的,你可以用它们做一些甚至c++ 20 Lambdas都不支持的事情。即,对自身和相关函数的纯递归调用。
例如,Collatz猜想是,某个简单的递归函数最终将对任何正整数N产生“1”。使用显式的局部结构体和函数,我可以编写一个单独的自包含函数来对任何“N”运行测试。
constexpr std::optional<int> testCollatzConjecture(int N) {
struct CollatzCallbacks {
constexpr static int onEven(int n) {
return recurse(n >> 1); // AKA "n/2"
}
constexpr static int onOdd(int n) {
if(n==1) return 1; // Break recursion. n==1 is only possible when n is odd.
return recurse(3 * n + 1);
}
constexpr static int recurse(int n) {
return (n%2) ? onOdd(n) : onEven(n); // (n%2) == 1 when n is odd
}
};
// Error check
if(N < 0) return {};
// Recursive call.
return CollatzCallbacks::recurse(N);
}
注意一些c++20 lambdas在这里不能做的事情:
I didn't need std::function<> glue OR lambda captures ("[&]") just to enable my local recursive functions call themselves, or each other. I needed 3 plain-old-functions with names, and that's all I had to write. My code is more readable and (due to (1)) will also run much faster. I cleanly separate the recursive logic in "CollatzCallbacks" from the rest of "testCollatzConjecture". It all runs in an isolated sandbox. I was able to make everything "constexpr" and state-less, so it can all run at compile time for any constant value. AFAIK I'd need c++23 just to achieve the recursion part with state-less lambdas.
记住:Lambda函数实际上只是编译器生成的局部结构体,如“CollatzCallbacks”,只是它们没有命名,并且只有一个“operator()”成员函数。您总是可以直接编写更复杂的局部结构和函数,特别是在您确实需要它们的情况下。