草庐IT

c++ - 从 std::ostream_iterator 调用时未找到运算符 << 的重载?

coder 2024-02-09 原文

这个程序

// main.cpp

#include <iostream>
#include <utility>
#include <algorithm>
#include <iterator>
#include <map>

template<typename t1, typename t2>
std::ostream& operator<<(std::ostream& os, const std::pair<t1, t2>& pair)
{
  return os << "< " << pair.first << " , " << pair.second << " >";
}

int main() 
{
  std::map<int, int> map = { { 1, 2 }, { 2, 3 } };
  std::cout << *map.begin() << std::endl;//This works

  std::copy(
    map.begin(),
    map.end(),
    std::ostream_iterator<std::pair<int,int> >(std::cout, " ")
  ); //this doesn't work
}

产生错误

no match for ‘operator<<’ (operand types are ‘std::ostream_iterator<std::pair<int, int> >::ostream_type {aka std::basic_ostream<char>}’ and ‘const std::pair<int, int>’)

我猜这是行不通的,因为我的重载在 std::copy 中不可用,但这是为什么呢?

最佳答案

说明

operator<<namespace std 内部(更具体地说是在 std::ostream_iterator 内部)以非限定方式调用,并且还声明了所有涉及的参数在同一个命名空间中,只有 命名空间std将搜索潜在的匹配项。


骇人听闻的解决方案

namespace std {
  template<typename t1, typename t2>
  std::ostream& operator<<(std::ostream& os, const std::pair<t1, t2>& pair)
  {
     return os << "< " << pair.first << " , " << pair.second << " >";
  }
}

注意:您只能在 namespace std 内特化包含用户定义类型的模板,因此根据标准,上述代码片段可能格式错误(如果 std::pair<T1,T2> 不是用户声明的类型,请参阅 this discussion )。


详细解释

下面我们有 namespace N 这将帮助我们尝试模拟您对 namespace std 的使用,以及当编译器试图找到合适的重载时会发生什么对于给定的类型。

命名空间 N

namespace N {
  struct A { };
  struct B { };

  void func (A value) { std::cout << "A"; }

  template<class T>
  void call_func (T value) { func (value); }
}

main.cpp

void func (N::B value) {
  std::cout << "B";
}

int main() {
  N::A a;
  N::B b;

  func (a);         // (1)
  func (b);         // (2)

  N::call_func (a); // (3a)
  N::call_func (b); // (3b)
}

注意事项:

  1. 在不了解参数相关查找的情况下,编译器能够找到使 (1) 工作所需的合适重载可能会让您感到惊讶。

    ADL 声明在函数调用中使用非限定名称 时,不仅会搜索当前命名空间以寻找合适的重载,还会搜索参数的命名空间;这就是编译器找到 N::func 的方式,即使我们没有写得那么明确。

  2. 我们在当前命名空间中有一个合适的重载;一切都很好。

  3. ...

    为什么 (3a) 编译,而 (3b) 会导致讨厌的诊断?

    当我们实例化模板时N::call_func<T>它将尝试传递 T 类型的参数到名为 funcunqualified 函数.

    因为 name-lookup 的规则说当前命名空间,涉及的参数的命名空间,在我们调用函数的情况下搜索合适的匹配项从一个不合格的名称,如果T,它将搜索 namespace N是在命名空间 N 中声明的类型。

    两者都是 N::AN::B命名空间 N 中声明,因此编译器不会搜索任何其他范围以找到合适的重载;这就是查找失败的原因。

关于c++ - 从 std::ostream_iterator 调用时未找到运算符 << 的重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24110928/

有关c++ - 从 std::ostream_iterator 调用时未找到运算符 << 的重载?的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby-on-rails - Nokogiri:使用 XPath 搜索 <div> - 2

    我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll

  5. ruby-on-rails - capybara ::ElementNotFound:无法找到 xpath "/html" - 2

    我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby - 如何找到调用当前方法的方法 - 2

    如何找到调用此方法的位置?defto_xml(options={})binding.pryoptions=options.to_hifoptions&&options.respond_to?(:to_h)serializable_hash(options).to_xml(options)end 最佳答案 键入caller。这将返回当前调用堆栈。文档:Kernel#caller.例子[0]%rspecspec10/16|===================================================62=====

  8. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  9. ruby - 带括号和 splat 运算符的并行赋值 - 2

    我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow

  10. ruby-on-rails - 没有参数的 `<<`(小于两倍)是什么意思? - 2

    我在一个我想在formtasticGem中覆盖的方法中找到了这个。该方法如下所示:defto_htmlinput_wrappingdohidden_field_html是什么意思?在第三行做什么?我知道它对数组有什么作用,但在这里我不知道。 最佳答案 你可以这样读:hidden_field_htmllabel_with_nested_checkbox是连接到hidden_​​field_html末尾的参数-为了“清晰”,他们将其分成两行 关于ruby-on-rails-没有参数的`

随机推荐