了解如何在编译时计算总和

Understand how to compute sum at compile time

本文关键字:计算 编译 了解      更新时间:2023-10-16

我有这段代码,想了解:

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