【问题标题】:Why can't gcc deduce templated size for array argument? (C++11)为什么 gcc 不能推断数组参数的模板大小? (C++11)
【发布时间】:2012-06-07 15:38:22
【问题描述】:

以下代码给出编译器错误(gcc-4.7 run with -std=c++11):

#include <iostream>
#include <array>

template <typename T, int N>
std::ostream & operator <<(std::ostream & os, const std::array<T, N> & arr) {
  int i;
  for (i=0; i<N-1; ++i)
    os << arr[i] << " ";
  os << arr[i];
  return os;
}

int main() {
  std::array<double, 2> lower{1.0, 1.0};
  std::cout << lower << std::endl;
  return 0;
}

错误信息:

tmp6.cpp:在函数“int main()”中:tmp6.cpp:16:16:错误:无法绑定
'std::ostream {aka std::basic_ostream}' 左值
'std::basic_ostream&&' 在包含的文件中
/usr/include/c++/4.7/iostream:40:0,
来自 tmp6.cpp:1: /usr/include/c++/4.7/ostream:600:5: 错误: 初始化‘std::basic_ostream<_chart>的参数1 _Traits>& std::operator&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits; _Tp = std::array]'

当我摆脱模板函数声明并将T替换为double并将N替换为2时,它编译得很好(编辑:离开T并将N替换为2 有效,但将 N=2 指定为 N 的默认参数不起作用。)。

  1. 有人知道为什么 gcc 不能自动绑定这个吗?
  2. 使用显式指定的模板参数调用&lt;&lt; 运算符的语法是什么?

问题 2 的答案: operator&lt;&lt;&lt;double, 2&gt;(std::cout, lower);

编辑:以下函数也是如此,它仅在数组大小中进行模板化:

template <int N>
void print(const std::array<double, N> & arr) {
  std::cout << "print array here" << std::endl;
}

int main() {
  std::array<double, 2> lower{1.0, 1.0};
  print<2>(lower); // this works
  print(lower);    // this does NOT work
  return 0;
}

非常感谢您的帮助。

【问题讨论】:

  • 请注意,您不应该为标准类型定义operator &lt;&lt;
  • @K-ballo 知道如何回答帖子中的两个编号问题吗?
  • 如果我能回答,我会给出答案而不是评论......问题可能来自以错误的方式实现运算符。
  • @K-ballo 可以使用函数template &lt;int N&gt; print (const std::array&lt;double, N&gt; &amp; arr) { /*...*/ } 提出相同的问题。我想知道为什么 gcc 不能绑定这个...
  • 你的意思是print( lower ); 不会编译?您能否将print 版本的测试用例添加到您的问题中?

标签: c++ templates gcc c++11


【解决方案1】:

考虑你的声明:

template <typename T, int N>
std::ostream & operator <<(std::ostream & os, const std::array<T, N> & arr) {

std::array 的定义是:

template<typename T, std::size_t N> class array {...};

您使用的是int 而不是std::size_t,这就是它不匹配的原因。

【讨论】:

  • 巨大的+1。非常感谢,我不确定我曾经会发现。
  • +1 我刚刚阅读标准 (14.8.2) 关于模板推导的内容,想知道我遗漏了什么,因为没有什么反对这种推导的。模板定义中的错误类型也引起了我的注意。
【解决方案2】:

您可以在此调用operator&lt;&lt; 并指定模板参数,而不是那么美观,方式:

operator<< <double,2>(std::cout, lower) << std::endl;

【讨论】:

  • +1 我不知道为什么我不尝试这样做——我对&lt;&lt;&lt; 如此着迷,以至于我认为编译器不会喜欢它(我想我正在投影)!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
相关资源
最近更新 更多