In C ++ lambda application scenarios and compiler implementation principle

First, the use scene

1, the scene requirements and restrictions of the local function

In the standard C ++ (before C ++ 11), the syntax is not of such a local function. However, in some scenarios, using local functions can greatly simplify the code, for example, a circle is an input parameter (represented by the center point and radius), given two points is determined, whether in a circle outside, an inside, in this case preferably has a function of determining whether a point inside the circular interface, and two points respectively judged.
Point struct
{
int X;
int Y;
};
BOOL IsTrue (Point & rstCenter, int iRadius, & Point Pl, P2 & Point)
{
BOOL PointInCircle (Point & rstPoint)
{
return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <* = iRadius iRadius;
}
return PointInCircle (Pl) = PointInCircle (P2);!
}

However, because C ++ does not allow the use of local function, the above code does not compile. Prior to the introduction of lambda functions, typically workaround is partially defined type, and function as the local use of the static function, but is not restricted to use where a local variable function.
tsecer @ Harry: CAT -n localstruct.cpp
. 1 struct Point
2 {
. 3 int X;
. 4 int Y;
. 5};
. 6 BOOL IsTrue (Point & rstCenter, int iRadius, Point & Pl, Point & P2)
. 7 {
. 8 struct localstruct
. 9 {
10 BOOL PointInCircle static (Point & rstPoint)
. 11 {
12 is return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <* = iRadius iRadius;
13 is}
14};
15 :: PointInCircle return localstruct (Pl) = localstruct :: PointInCircle (P2);!
16}
tsecer Harry @: G ++ localstruct.cpp -C
localstruct.cpp: 在静态成员函数‘static bool IsTrue(Point&, int, Point&, Point&)::localstruct::PointInCircle(Point&)’中:
localstruct.cpp:12:25: 错误:use of parameter from containing function
return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <= iRadius * iRadius;
^
localstruct.cpp:6:6: 错误:‘Point& rstCenter’已在此声明过
bool IsTrue(Point &rstCenter, int iRadius, Point &P1, Point &P2)
^
localstruct.cpp:12:54: 错误:use of parameter from containing function
return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <= iRadius * iRadius;
^
localstruct.cpp:6:6: 错误:‘Point&rstCenter 'has been declared in this
bool IsTrue(Point &rstCenter, int iRadius, Point &P1, Point &P2)
^
localstruct.cpp:12:83: 错误:use of parameter from containing function
return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <= iRadius * iRadius;
^
localstruct.cpp:6:6: 错误:‘Point& rstCenter’已在此声明过
bool IsTrue(Point &rstCenter, int iRadius, Point &P1, Point &P2)
^
localstruct.cpp:12:112: 错误:use of parameter from containing function
return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <= iRadius * iRadius;
^
localstruct.cpp:6:6: 错误:‘Point& rstCenter’已在此声明过
IsTrue BOOL (Point & rstCenter, int iRadius, & Point Pl, P2 & Point)
^
localstruct.cpp: 12 is: 128: Error: Parameter use of function containing from
return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter. X) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <* = iRadius iRadius;
^
localstruct.cpp:. 6:. 6: error: 'int iRadius' is here declared
bool IsTrue (Point & rstCenter, int iRadius, & Point Pl, P2 & Point)
^
localstruct.cpp: 12 is: 138: error: Parameter use of function containing from
return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <* = iRadius iRadius;
^
localstruct.cpp:. 6:. 6: error: 'int iRadius' is here declared
bool IsTrue(Point &rstCenter, int iRadius, Point &P1, Point &P2)
^
tsecer@harry:

 

2, the solution of lambda functions

tsecer@harry: cat -n locallambda.cpp
1 struct Point
2 {
3 int x;
4 int y;
5 };
6
7 bool IsTrue(Point &rstCenter, int iRadius, Point &P1, Point &P2)
8 {
9 auto PointInCircle = [&](Point &rstPoint) -> bool
10 {
11 return (rstPoint.x - rstCenter.x) * (rstPoint.x - rstCenter.x) + (rstPoint.y - rstCenter.y) * (rstPoint.y - rstCenter.y) <= iRadius * iRadius;
12 };
13 return PointInCircle(P1) != PointInCircle(P2);
14 }
tsecer@harry: g++ -c -std=c++11 locallambda.cpp
tsecer@harry:
tsecer@harry:

Second, the realization principle

Generally speaking, gcc achieving lambda function, which corresponds to a local variable to allow reference to the function where the declaration statement by capturing, capturing these variable in a structure, a function operator and define in the structure. These look and compare yourself to achieve similar, but the difference is that it adds syntax, allowing for a clear statement of a local variable references, and will help to automatically calculate lambda function which cited local variables where the function to generate the corresponding types and operators compile time .
@ Harry tsecer: CAT -n autofunc.cpp
. 1 #include <Functional>
2
. 3 :: function typedef STD <BOOL (int, int)> stdFunc;
. 4
. 5 int main (int argc, char const * the argv [])
. 6 {
. 7 int A, B, C, D;
. 8 Auto FF = [&] (int X, int Y) -> BOOL
. 9 {
10 return X + Y + A + D;
. 11};
12 is
13 is FF (0x1111, 0x2222) ;
14
15 FF = stdFunc stdff;
16 stdff (0x3333, 0x4444);
. 17}
tsecer Harry @: G = C ++ ++ -g -std. 11 autofunc.cpp
tsecer @ Harry: GDB ./a.out
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/harry/study/autofunc/a.out...done.
(gdb) b main
Breakpoint 1 at 0x400874: file autofunc.cpp, line 11.
(gdb) r
Starting program: /home/harry/study/autofunc/./a.out

Breakpoint 1, main (argc=1, argv=0x7fffffffe578) at autofunc.cpp:11
11 };
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.tl2.3.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64
(gdb) ptype ff
type = struct __lambda0 {
int &__a;
int &__d;
}
(gdb) s
13 ff(0x1111, 0x2222);
(gdb)
__lambda0::operator() (__closure=0x7fffffffe460, x=4369, y=8738) at autofunc.cpp:10
10 return x + y + a + d;
(gdb) ptype __closure
type = const struct __lambda0 {
int &__a;
int &__d;
} * const
(gdb)

It can be seen that, since the lambda functions ff references local variables a, b, compiler dynamically generates such a structure compiles
struct __lambda0 {
int & __ A;
int & __ D;
BOOL operator () (int X, int Y)
{
return X __A __B + Y + +;
}
}
the this pointer disassembly of the structure may also be regarded as __closure.

Third, and std library functional interactions

After implementation principle we know it, and it can be used together std :: function, and defines the structure and the function call to use the same operator:
tsecer @ Harry: CAT -n lambdabind.cpp
. 1 #include <Functional>
2
typedef STD :: function. 3 <int (int, int)> stdFunc;
. 4
. 5 int main (int argc, char const * the argv [])
. 6 {
. 7 Auto FF = [&] (int X) -> int
. 8 {
. 9 X + argc return;
10};
. 11 stdFunc STD :: = stdff the bind (FF, STD :: _ :: placeholders. 1);
12 is return stdff (. 11, 22 is);
13 is}
14
tsecer Harry @: G ++ = -g -std ++ 11 lambdabind.cpp c
tsecer @ harry: ./a.out
tsecer @ harry: echo $?
12

Guess you like

Origin www.cnblogs.com/tsecer/p/12157887.html