简体   繁体   English

C ++模板中的类型优先级和整数类型

[英]Type precedence and integer types in C++ templates

I was using std::accumulate as part of coding exercise and came across some behaviour I want to understand more fully. 我在编码练习中使用了std :: accumulate,遇到了一些我想更全面理解的行为。

The signature of accumulate is: 累积的签名是:

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

If I have code like: 如果我有类似的代码:

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

it works as I'd expect. 它按我的预期工作。 If I change it to: 如果我将其更改为:

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

then I get overflows since (I think) the type of '0' is determined to be a 32bit integer, and this override the return type I actually specified (since a normal integer can be stored in a 64bit integer). 然后会溢出,因为(我认为)“ 0”的类型被确定为32位整数,并且此值覆盖了我实际指定的返回类型(因为可以将普通整数存储在64位整数中)。

From this I infer that the compiler is generating an accumulate that looks like: 据此,我推断出编译器正在生成如下所示的累加:

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

vs.

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

Is there some rule I can remember to generalise this inference to other cases? 我是否记得有一些规则可以将此推论推广到其他情况?

The signature of accumulate is: 累积的签名是:

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

The signature of accumulate is 累积的签名是

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

Don't forget the template arguments! 不要忘记模板参数! Templates would be a royal pain to use if one always had to specify the types. 如果模板总是必须指定类型,那么使用模板将是一种皇家痛苦。 The compiler (sometimes) nicely infers what those template arguments are based on the arguments you supply. 编译器(有时)会根据您提供的参数很好地推断出这些模板参数是什么。

This is one of those cases where it can and does do so. 这是它可以并且确实这样做的情况之一。 In this case, it infers that InputIt is std::vector<int>::iterator and that T is either std::int64_t (your first example) or int (your second example). 在这种情况下,它推断InputItstd::vector<int>::iterator ,而T要么是std::int64_t (您的第一个示例)或int (您的第二个示例)。

Unless you tell the compiler otherwise, it will always infer 0 to be of type int . 除非您另行告诉编译器,否则它将始终推断0int类型。 There is a way to tell the compiler that 0 is of some other type: 有一种方法可以告诉编译器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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM