首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >命名空间和带有stl算法的用户定义运算符。

命名空间和带有stl算法的用户定义运算符。
EN

Stack Overflow用户
提问于 2014-03-13 16:25:23
回答 2查看 132关注 0票数 1

当我试图通过std::copy输出元素时,我遇到了令人费解的行为。下面的代码正在编译,并且工作正常。

代码语言:javascript
复制
namespace Foo {
  enum class Colors { green, red, blue };

  template <typename T>
  std::ostream &operator << (std::ostream &_os, const T &_t) {
      _os << typename std::underlying_type<T>::type(_t);
      return _os;
  }
}

int main() {
  Foo::Colors colors[] = {Foo::Colors::red, Foo::Colors::red, Foo::Colors::blue};

  for( auto c: colors ) { std::cout << c <<std::endl; }

  std::copy(colors, colors + 4, std::ostream_iterator<Foo::Colors>(std::cout, " "));
}

但是,如果我将operator <<转移到Foo作用域之外,std::copy就会出现问题。

代码语言:javascript
复制
namespace Foo {
  enum class Colors { green, red, blue };
}

template <typename T>
std::ostream &operator << (std::ostream &_os, const T &_t) {
  _os << typename std::underlying_type<T>::type(_t);
  return _os;
}

int main() {
  Foo::Colors colors[] = {Foo::Colors::red, Foo::Colors::red, Foo::Colors::blue};

  for( auto c: colors) { std::cout << c <<std::endl; } // works fine

  // arising compiler error
  std::copy(colors, colors + 4, std::ostream_iterator<Foo::Colors>(std::cout, " ")); 

  // do not help, too
  {
    using namespace Foo;
    std::copy(colors, colors + 4, std::ostream_iterator<Colors>(std::cout, " ")); 
  }
}

此行为的原因是什么,以及解决此问题的正确方法是什么?

EN

回答 2

Stack Overflow用户

发布于 2014-03-13 16:30:55

您的模板正在接受所有内容,并将导致模棱两可:

一个较小的测试用例:

代码语言:javascript
复制
#include <iostream>

// error: ambiguous overload for ‘operator<<’ in ‘std::cout << '\012'’
template <typename T>
std::ostream &operator << (std::ostream &_os, const T &_t) {
  _os << typename std::underlying_type<T>::type(_t);
  return _os;
}

int main() {
    std::cout << '\n';
}

只有一个且只有一个(!)由于ADL (参数相关查找),命名空间中的运算符<<将解析它。

票数 4
EN

Stack Overflow用户

发布于 2014-03-13 19:06:20

原因是std::ostream_iterator<Foo::Colors>搜索operator<<,而它本身在名称空间std中。通常的非限定查找将只在包含具有该名称的函数的最近封闭类或命名空间中查找函数。例如:

代码语言:javascript
复制
void meow(int);
namespace foo
{
    void meow(double);

    void find_kitten()
    {
        meow(42); // calls `foo::meow(double)`
    }
}

同样的事情也发生在operator<<身上。在名称空间std中存在此运算符的重载,因此,非限定名称查找停止并且不搜索全局名称空间。

但是,对于运算符,始终会发生参数相关的查找。如果您的函数模板位于某个参数类型的关联命名空间中,它将找到您的函数模板。这是第一个示例中的情况,但不是第二个示例中的情况。

附注:

请编译并显示警告,您的函数模板缺少返回值:

代码语言:javascript
复制
std::ostream &operator << (std::ostream &_os, const T &_t) {
  _os << typename std::underlying_type<T>::type(_t);
  return _os; // <--- missing
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22372886

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档