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

时间:2013-09-07 18:15:44

标签: c++ c++11 variadic-templates template-specialization template-meta-programming

我有这段代码,想要了解:

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; }; 
};

3 个答案:

答案 0 :(得分:7)

请注意,语法略有不同。声明主模板时:

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 }; 
};

您正在尝试制作两个具有相同名称的不同类模板,这是不允许的。

请注意,这与功能模板的工作方式略有不同。使用函数模板,您可以执行重载,因此可以使用具有相同名称的多个函数模板。但是对于函数模板,您不能进行部分特化,因为这会产生很多歧义。

您可能认为主模板和专业化之间存在歧义,但更专业化的专业化总是优先于专业性较低的专业化,而主要模板始终被认为是最不专业化的。如果不是这样,那么部分专业化根本不起作用。

答案 1 :(得分:0)

第一个声明:

template<unsigned int... Ns>
struct sum;

是前向声明:它将模板声明为具有可变数量的unsigned int参数的模板。

第一个特化是元函数的基本情况,它保留了variadic-pack只有一个参数的情况:

template<unsigned size>
struct sum<size>
{
    enum {value = size};
};

第二个特化是递归的情况:它保留了variadic-pack至少有一个参数的情况:

template<unsigned size, unsigned... sizes>
struct sum<size, sizes...>
{
    enum { value = size + sum<sizes...>::value }; 
};

我建议您在编写/学习模板元编程之前,先了解有关C ++模板机制(如即时,模板专业化等)的更多信息。

答案 2 :(得分:0)

借助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