了解如何在编译时计算总和
Understand how to compute sum at compile time
我有这段代码,想了解:
template <unsigned...>
struct sum;
template<unsigned size>
struct sum<size>
{
enum {value = size};
};
template<unsigned size, unsigned... sizes>
struct sum<size, sizes...>
{
enum { value = size + sum<sizes...>::value };
};
int _tmain(int argc, _TCHAR* argv[])
{
sum<1, 2>::value;
return 0;
}
我不明白为什么未实现的总和(需要未签名...就像最后一个结构专用化一样,没有冲突吗?必须存在,以及如何使用模板部分中的相同参数(e.g. sum<size, sizes...>
与template <unsigned size, sizes...>
相同)来专门化总和。为什么波纹管不起作用?
template<unsigned size>
struct sum
{
enum {value = size};
};
template<unsigned size, unsigned... sizes>
struct sum
{
enum { value = size + sum<sizes...>::value; };
};
请注意,语法有点不同。 声明主模板时:
template <unsigned...>
struct sum;
您不会在 sum
之后提供模板参数。 这是因为您正在创建一个全新的模板,并说它采用任意数量的无符号整数作为参数。
执行此操作时:
template<unsigned size, unsigned... sizes>
struct sum<size, sizes...>
{
enum { value = size + sum<sizes...>::value };
};
您正在专门使用之前声明的模板。 您是说,如果您的参数由一个无符号值后跟任意数量的其他无符号值组成,请使用此定义。 这与主模板不完全相同。 主模板包括零参数的可能性。
当您尝试执行此操作时:
template<unsigned size>
struct sum
{
enum { value = size };
};
template<unsigned size, unsigned... sizes>
struct sum // OOPS! A template called `sum` has already been declared!
{
enum { value = size + sum<sizes...>::value };
};
您正在尝试创建两个具有相同名称的不同类模板,这是不允许的。
请注意,这与函数模板的工作方式略有不同。 使用函数模板,可以执行重载,因此可以使用多个同名的函数模板。 但是,对于函数模板,不能执行部分专用化,因为这会产生很多歧义。
您可能认为主模板和专业化之间存在歧义,但更专业的专业化始终优先于不太专业化的专业化,并且主模板始终可以被视为最不专业的。 如果这不是真的,那么部分专业化根本行不通。
第一个声明:
template<unsigned int... Ns>
struct sum;
是一个前向声明:它将模板声明为具有可变数量的unsigned int
参数的模板。
第一个特化是元函数的基本情况,它包含可变变量包只有一个参数的情况:
template<unsigned size>
struct sum<size>
{
enum {value = size};
};
第二个特化是递归情况:当可变包至少有一个参数时,它成立的情况:
template<unsigned size, unsigned... sizes>
struct sum<size, sizes...>
{
enum { value = size + sum<sizes...>::value };
};
我建议您在编写/学习模板元编程之前,先了解有关C++模板机制(如即时化、模板专用化等)的更多信息。
使用 c++20 的新功能,您可以像这样解决问题:
-
使用许多参数初始化
struct
:template<int ...args>
-
您的结果将是
const auto
。static const auto value = (0 + ... + args);
-
auto
关键字是在 C++17 中定义的,能够推断函数的返回类型。
法典:
<小时 />#include <iostream>
template<int ...args>
struct sum
{
static const auto value = (0 + ... + args);
};
int main(int argc, char *argv[])
{
const auto res = sum<10, 20, 40, -5>();
std::cout << "Result ";
std::cout << res.value;
std::cout << std::endl;
return 0;
}
结果:
Result 65
- 断言中的Fold表达式在某些计算机上编译,但在其他计算机上不编译
- C++ 在编译时具有函数计算全局变量
- 如何在常量计算表达式中获取编译时错误?
- 如何判断是否在编译时计算了"constexpr"(无需手动检查)
- 在编译时何时计算范围::视图?
- C++编译器能在编译时计算出文字的除法结果吗
- 在编译时计算"if"子句
- 根据计算机上安装的库依赖项编译不同的代码
- 强制在编译时计算类的类的常量成员
- 在 64 位 Linux armv8 计算机上编译 32 位二进制文件时遇到问题
- 在编译时计算基类的偏移量
- C++ constexpr:在编译时计算标准数组
- 如何判断表达式是在编译时还是运行时计算的?
- 计算对数组编译时中对元素的差异
- C++ 计算编译时常量,同时防止整数常量溢出
- 在C++中,是否有内置的方法来计算编译时的功率
- 如何使用工会成员的大小计算编译时值
- 如何驱动 C#、C++ 或 Java 编译器计算 1+2+3+.编译时为 +1000
- 计算编译时数组时出现编译器相关错误
- 在C++11中计算编译时的斐波那契数(递归方法)(constexpr)