操作符重载解析在命名空间中如何工作? [英] How does the operator overload resolution work within namespaces?

查看:127
本文介绍了操作符重载解析在命名空间中如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现一个奇怪的C ++解析操作符重载的行为,我不能解释自己。

I found a strange behaviour of C++ resolution of operator-overloading, I can't explain myself. A pointer to some resource describing it would be just as nice as an answer.

我有两个翻译单元。在一个(称为util.cpp / h)我声明和定义两个运算符(我省略了可读性的实际实现,无论如何,problam发生):

I have 2 translation units. In one (called util.cpp/h) I declare and define two operators (I omit the real implementations for readabilty, the problam occurs anyway):

// util.h
#ifndef GUARD_UTIL
#define GUARD_UTIL

#include <iostream>

std::istream& operator>>(std::istream& is, const char* str);
std::istream& operator>>(std::istream& is, char* str);
#endif

和:

//util.cpp
#include "util.h"
#include <iostream>

std::istream& operator>>(std::istream& is, const char* str) {
  return is;  
}
std::istream& operator>>(std::istream& is, char* str) {
  return is;  
}

如果这些操作符在全局命名空间中,和内置类型,应该可以从任何地方使用。他们只是从全局命名空间(例如从main())或明确告诉编译器他们在全局命名空间(见代码示例)。工作正常。

These operators are, if course in global namespace, since they operate on std types and built-in types and should be usable from everywhere. They just work fine from global namespace (e.g. from main()) or with explicitly telling the compiler that they are in global namespace (see code example).

单元(称为test.cpp / h)我在命名空间中使用这些运算符。这工作,直到我把一个类似的操作符到这个命名空间。一旦添加了此运算符,编译器(例如gcc或clang)就不能再找到可行的运算符>>。

In another translation unit (called test.cpp/h) I use these operators within a namespace. This works until I put a similar operator into this namespace. As soon as this operator is added, the compiler (e.g. gcc or clang) is not able to find a viable operator>> anymore.

// test.h
#ifndef GUARD_TEST
#define GUARD_TEST

#include <iostream>

namespace Namespace {
  class SomeClass {   
    public:
      void test(std::istream& is);
  };

  // without the following line everything compiles just fine
  std::istream& operator>>(std::istream& is, SomeClass& obj) { return is; }; 
}

#endif

和:

//test.cpp
#include "test.h"
#include "util.h"
#include <iostream>

void Namespace::SomeClass::test(std::istream& is) {
  ::operator>>(is, "c"); //works
  is >> "c" //fails
}

为什么编译器找到正确的操作符在命名空间中没有操作符>>但是在有一个时却找不到?为什么操作符影响编译器找到正确的标识符的能力,即使它有不同的签名?

Why does the compiler find the correct operator when there is no operator>> in Namespace but fails to find when there is one? Why does the operator affect the ability of the compiler to find the correct one even if it has a different signature?

一个尝试修复这个问题的方法是把

One attempt to fix this was to put

std :: istream& operator >>(std :: istream& is,const char * str){:: operator >>(is,str); }

std::istream& operator>>(std::istream& is, const char* str) { ::operator>>(is, str); }

放入命名空间,但是链接器不会提示以前的定义。所以额外的:为什么链接器找到编译器找不到的东西?

into Namespace, but than the linker complains about previous definitions. So additional: Why can the linker find something the compiler doesn't find?

推荐答案

这是一个名称隐藏问题。标准说(c ++ 03,3.3.7 / 1)

This is a name hiding issue. The standard says (c++03, 3.3.7/1)


名称可以通过同名的显式声明隐藏在嵌套的声明区域或派生的
类(10.2)。

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).

您的案例的名称 c $ c> operator>> 和命名空间构成嵌套的声明区域。

The "name" on your case would be operator>> and namespaces constitute nested declarative regions.

最简单的解决方法是使用使用声明,声明namespace-local 运算符<

The easiest way to fix that would be to use a using declaration where you declare the namespace-local operator<<:

namespace your_namespece {
    std::istream& operator>>(std::istream& is, SomeClass& obj) { return is; }; 
    using ::operator>>;
}

case,原则上它可以),因此仍然会找到 std :: 的I​​O运算符。

Note that this feature doesn't interfere with Koenig lookup (at least in your case, in principle, it can), so IO operators from std:: will still be found.

PS :另一种工作方式可能是将 SomeClass 的运算符定义为 inline friend 。这样的函数在命名空间级别(他们的类之外)被声明,但是从那里不可见。它们只能通过Koenig查找找到。

PS: Another possibility for working aroud this issue would be defining the operator for SomeClass as an inline friend. Such functions are declared at the namespace level (outside of "their" class), but are not visible from there. They can only be found by Koenig lookup.

这篇关于操作符重载解析在命名空间中如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆