[英]C++ functional programming code snippets
我一直致力于一个名为C ++ 11/14的功能编程特性的项目(我的大学之一)。 关于这些主题有几个现有的来源和类似的演示文稿,我发现不久前的一个包含几个我完全无法理解的代码片段(并且不知何故它们可以连接到函数式编程)。 片段A和B属于递归 , 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
。 这将在编译时计算。
这也是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
static
和const
,并且使用initializer list
初始化为0
(对于int
, int 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>
, i
是1
, tail
是2, 3
。 value
是i + 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
再次调用相同的函数,但现在参数包是空的! 所以value
是1 + 2 + 3 + my_sum<>::value
。 my_sum<>::value
为0
(定义),因此value = 1 + 2 + 3 + 0
。
计算表达式,但程序不会崩溃,因为计算时的表达式是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.