官术网_书友最值得收藏!

Functional programming associated with C++

Functional programming is another addition to C++ that provides the user with compiler assistance, in the form of lambda functions. Currently, this must be carried out by hand in C.

In C, a functional programming construct can be achieved using a callback. For example, consider the following code:

void
guard(void (*ptr)(int *val), int *val)
{
lock();
ptr(val);
unlock();
}

void
inc(int *val)
{
*val++;
}

void
dec(int *val)
{
*val--;
}

void
foo()
{
int count = 0;
guard(inc, &count);
guard(dec, &count);
}

In the preceding code example, we create a guard function that locks a mutex, calls a function that operates on a value, and then unlocks the mutex on exit. We then create two functions, one that increments a value given to it, and one that decrements a value given to it. Finally, we create a function that instantiates a count, and then increments the count and decrements the count using the guard function.

There are a couple of issues with this code:

  • The first issue is the need for pointer logic to ensure we can manipulate the variable we wish to operate on. We are also required to manually pass this pointer around to keep track of it. This makes the APIs clunky, as we have a lot of extra code that we have to write manually for such a simple example. 
  • The function signature of the helper functions is static. The guard function is a simple one. It locks a mutex, calls a function, and then unlocks it. The problem is that, since the parameters of the function must be known while writing the code instead of at compile time, we cannot reuse this function for other tasks. We will need to hand-write the same function for each function signature type we plan to support. 

The same example can be written using C++ as follows:

template<typename FUNC>
guard(FUNC f)
{
lock();
f();
unlock();
}

void
foo()
{
int count = 0;
guard(inc, [&]{ count++ });
guard(inc, [&]{ count-- });
}

In the preceding example, the same functionality is provided, but without the need for pointers. In addition, the guard function is generic and can be used for more than one case. This is accomplished by leveraging both template programming and functional programming.

The lambda provides the callback, but the parameters of the callback are encoded into the lambda's function signature, which is absorbed by the use of a template function. The compiler is capable of generating a version of the guard function for use that takes the parameters (in this case, a reference to the count variable) and storing it in the code itself, removing the need for users to do this by hand. 

The preceding example will be used a lot in this book, especially when creating benchmarking examples, as this pattern gives you the ability to wrap functionality in code designed to time the execution of your callback. 

主站蜘蛛池模板: 普兰县| 禄丰县| 临武县| 独山县| 廊坊市| 亚东县| 本溪| 云和县| 井研县| 隆林| 无锡市| 金山区| 甘南县| 光山县| 资中县| 墨脱县| 城步| 沁源县| 和林格尔县| 惠东县| 西华县| 天长市| 长宁区| 呼伦贝尔市| 定襄县| 天镇县| 邮箱| 油尖旺区| 紫阳县| 彭州市| 泰顺县| 关岭| 固原市| 罗源县| 静宁县| 靖西县| 淮安市| 河间市| 道孚县| 松原市| 安塞县|