繁体   English   中英

C ++函数式编程代码片段

[英]C++ functional programming code snippets

我一直致力于一个名为C ++ 11/14的功能编程特性的项目(我的大学之一)。 关于这些主题有几个现有的来源和类似的演示文稿,我发现不久前的一个包含几个我完全无法理解的代码片段(并且不知何故它们可以连接到函数式编程)。 片段AB属于递归C属于懒惰评估 我想在下面与您分享:

片段A

#include <iostream>

template <int N>
struct Factorial {
    static int const val = N * Factorial<N - 1>::val;
};

template <>
struct Factorial <0> {
    static int const val = 1;
};

int main() {
    int factorial_of_6 = Factorial<6>::val;
    std::cout << factorial_of_6 << std::endl;
    return 0;
}

这里的重点是编译时评估(为了避免运行时计算并提高性能)? 或者还有其他优点吗?

代码片段B

#include <iostream>

template <int ...>
struct my_sum;

template <>
struct my_sum <> {
    static const int value {0};
};

template <int i, int ... tail>
struct my_sum <i, tail ...> {
    static const int value = i + my_sum<tail ...>::value;
};

int main() {
    int sum {my_sum<1, 2, 3, 4, 5>::value};
    std::cout << sum << std::endl;
    return 0;
}

同样的问题适用于上述。

这是另一个可能类似的片段:

片段C

#include <iostream>

template <typename... Args>
void some_function (Args ...) {
    std::cout << sizeof...(Args) << std::endl;
}

int main() {
    some_function ("Every little thing gonna be alright...", 1.0 / 0.0);
    return 0;
}

“该演示文稿说:C ++非常渴望,但以下内容将起作用。” 重点是,在我不关心给定的表达式之前,我可以告诉它们的数量吗?

请尽可能详细和详细,非常感谢您的耐心和帮助。 :)

片段A.

这称为Template Metaprogramming ,它基本上是一种使用模板在编译时生成代码的技术。 这会增加运行时性能,因为计算不是在运行时完成的,而是在编译时完成的。

calculates the factorial of a given number at compile time: 在编译时计算给定数字的阶乘:

template <int N>
struct Factorial {
    static int const val = N * Factorial<N - 1>::val;
};

这将struct Factorial定义为采用int的模板。 在该struct ,有一个static const变量。 变量是static ,因此您不必创建Factorial实例来访问它,您只需使用Factorial::val而不是

Factorial factorial;
factorial.val;

变量是const因为给定数字的阶乘总是相同的,并且因为如果项目不是const ,项目将不会编译,因为编译器无法知道您是否在其他地方更改了变量。

变量的值为N * Factorial<N - 1::val; ,它基本上将N乘以前一个数的阶乘。 这是因为如何定义阶乘( 3! = 2! * 3 = 1! * 2 * 3 = 1 * 2 * 3 = 6 )。

template <>
struct Factorial <0> {
    static int const val = 1;
};

这为N = 0定义了一个完全专用的struct 这非常重要,否则前一个函数中使用的递归将永远不会停止。

然后,得到数N的阶乘是容易的, Factorial<N>::val 这将在编译时计算。


代码片段B.

这也是Template Metaprogramming

 template <int ...> struct my_sum; 

这定义了一个空的模板struct ,它接受一个int... (一个Parameter Pack ),以便它可以被专门化(见下一点)。

 template <> struct my_sum <> { static const int value {0}; }; 

当没有给出模板参数时,这就特化了struct my_sum (这是因为Parameter Pack可以为空,因此扩展Parameter Pack时模板参数将为空)。 由于与之前相同的原因,该value staticconst ,并且使用initializer list初始化为0 (对于intint i = 0;int i{ 0 }; )之间没有区别。

 template <int i, int ... tail> struct my_sum <i, tail ...> { static const int value = i + my_sum<tail ...>::value; }; 

这将struct my_sum定义为一个模板,它带有2个模板参数,一个int和一个int参数包。 这用于获取参数包的第一个值,因为您无法索引参数包(它不是数组)。 然后, value被初始化为i (该包装件的第一值)加上value的其他值作为参数组,其被膨胀的(使用... ):

 int sum = my_sum<1, 2, 3>::value; 

这调用my_sum<int i, int... tail>i1tail2, 3 valuei + my_sum<tail...>::value ,所以它是1 + my_sum<2, 3> my_sum<2, 3>再次调用相同的函数, 2 + my_sum<3>::value 现在我们有1 + 2 + my_sum<3>::value my_sum<3>::value再次调用相同的函数,但现在参数包是空的! 所以value1 + 2 + 3 + my_sum<>::value my_sum<>::value0 (定义),因此value = 1 + 2 + 3 + 0


代码片段C.

计算表达式,但程序不会崩溃,因为计算时的表达式是double 只有当表达式为int ,它才会因Integer division by zero exception而崩溃。 如果你这样做:

 int zero = 0; double d = 1.0 / zero; 

然后d将具有值inf

函数some_function是一个模板函数,它将参数包作为模板参数。 然后它调用sizeof...来计算参数包中的元素,并使用std::cout输出它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM