【问题标题】:Type precedence and integer types in C++ templatesC++ 模板中的类型优先级和整数类型
【发布时间】:2016-02-27 17:02:45
【问题描述】:

我在编码练习中使用 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);

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

由此我推断编译器正在生成一个累加,如下所示:

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

对比

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

我记得有什么规则可以将此推论推广到其他情况吗?

【问题讨论】:

  • 你是故意混合类型吗?
  • 是的,我得到一个整数向量并且需要求和,因此溢出是一个问题。
  • 我知道向量中的 'int' 是 32 位签名的。

标签: c++ templates


【解决方案1】:

累加的签名是:

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

累加的签名是

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

不要忘记模板参数!如果总是必须指定类型,那么使用模板将是一件非常痛苦的事情。编译器(有时)可以根据您提供的参数很好地推断出这些模板参数是什么。

这是它可以并且确实这样做的情况之一。在这种情况下,它推断InputItstd::vector&lt;int&gt;::iterator 并且Tstd::int64_t(您的第一个示例)或int(您的第二个示例)。

除非你告诉编译器,否则它总是会推断出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

【讨论】:

  • 我希望int64_t(0) 更具体。
猜你喜欢
  • 1970-01-01
  • 2011-03-22
  • 2014-07-05
  • 2021-08-15
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多