在C ++模板中键入优先级和整数类型

时间:2016-02-27 17:02:45

标签: c++ templates

我使用std :: accumulate作为编码练习的一部分,并且遇到了一些我想要更全面理解的行为。

累积的签名是:

T accumulate( InputIt first, InputIt last, T init );

如果我的代码如下:

std::vector<int> a = {..};
int64_t zero = 0;
int64_t csum = std::accumulate(a.begin(), a.end(), zero);

它像我期待的那样有效。如果我将其更改为:

std::vector<int> a = {..};
int64_t csum = std::accumulate(a.begin(), a.end(), 0);

然后我得到溢出,因为(我认为)&#39; 0&#39;被确定为32位整数,并且这会覆盖我实际指定的返回类型(因为普通整数可以存储在64位整数中)。

由此我推断编译器正在生成一个类似于:

的累积
int accumulate( InputIt first, InputIt last, int init );

VS

int64_t accumulate( InputIt first, InputIt last, int64_t); 

是否有一些规则可以记住将这种推断推广到其他案例?

1 个答案:

答案 0 :(得分:1)

  

累积的签名是:

T accumulate( InputIt first, InputIt last, T init );

累积的签名是

template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );

别忘了模板参数!如果总是必须指定类型,模板将是一种皇家的痛苦。编译器(有时)很好地推断出那些模板参数是基于你提供的参数。

这是可以并且确实这样做的情况之一。在这种情况下,它会推断InputItstd::vector<int>::iteratorTstd::int64_t(您的第一个示例)或int(您的第二个示例)。< / p>

除非您告诉编译器,否则它始终会将0推断为类型int。有一种方法可以告诉编译器0是其他类型的:

std::accumulate(a.begin(), a.end(), 0L)   // T is long int
std::accumulate(a.begin(), a.end(), 0LL)  // T is long long int
std::accumulate(a.begin(), a.end(), 0U)   // T is unsigned int
std::accumulate(a.begin(), a.end(), 0UL)  // T is unsigned long int
std::accumulate(a.begin(), a.end(), 0ULL) // T is unsigned long long int