【问题标题】:Unnamed namespace and iostream result in "!= being illegal operation"未命名的命名空间和 iostream 导致“!=被非法操作”
【发布时间】:2011-12-13 11:59:01
【问题描述】:
#include <functional>
#include <iostream>

struct A {
    friend bool operator==( const A & a, const A & b ){
        return true;
    }
};

namespace {
    bool operator!=( const A &a, const A & b){
        return !(a==b);
    }
}

int main(int argc, char **argv) {
    std::not_equal_to<A> neq;
    A a;

    bool test = neq(a, a);

    return test ? 0 : 1;
}

这在CC(SunOs 编译器)上失败:

Error: The operation "const A != const A" is illegal.
"tempcc.cpp", line 16:     Where: While instantiating "std::not_equal_to<A>::operator()(const A&, const A&) const".
"tempcc.cpp", line 16:     Where: Instantiated from non-template code.

g++ 上使用:

/usr/local/include/c++/3.3.2/bits/stl_function.h: In member function `bool std::not_equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A]':
tempcc.cpp:16:   instantiated from here
/usr/local/include/c++/3.3.2/bits/stl_function.h:183: error: no match for 'operator!=' in '__x != __y'

但是,如果我删除 #include &lt;iostream&gt; 行,它将编译并运行得很好。有人敢解释吗?

【问题讨论】:

  • IdeOne 上根本不起作用,即使删除了 #include &lt;iostream&gt;
  • 以上都来自SunOS。我也在 AIX 上使用 g++ 进行了尝试,结果是相同的(使用 iostream 它不会编译,没有它会编译)。如果没有其他人在我之前尝试过,我将尝试在 Linux 上运行它以查看它的作用。
  • @Seth 可能是。但随后删除“命名空间{}”也解决了这个问题。而且我认为如果是您链接的情况,则不应该这样做。我必须考虑更多。
  • 以前试过。不会改变任何事情。但似乎它们是密切相关的问题。

标签: c++ functional-programming g++ iostream sunos


【解决方案1】:

根据 Comeau 的说法,这两种方式都是不合法的——编译器在你不#include &lt;iostream&gt; 时构建它的事实可能是实际的错误,而不是相反(或者至少是解释上的分歧) :

"stl_function.h", line 99: error: no operator "!=" matches these operands
            operand types are: const A != const A
    bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; }
                                                                       ^
          detected during instantiation of "bool
                    std::not_equal_to<_Tp>::operator()(const _Tp &, const _Tp
                    &) const [with _Tp=A]" at line 19 of "ComeauTest.c"

"ComeauTest.c", line 10: warning: function "<unnamed>::operator!=" was declared but
          never referenced
      bool operator!=( const A &a, const A & b){
           ^

这是有道理的,这不会构建 - 将 operator!= 放置在未命名的命名空间中仍然会将其置于与 :: 不同的命名空间中,我不完全确定为什么 g++ 在没有 iostream 包含的情况下构建它- 如果您查看 g++ 的预处理器输出,它并没有对代码重新排序或任何此类废话做任何事情,当然iostream 没有为A 定义operator!=

我手头没有 C++ 标准的副本,但来自 IBM 的 this link 至少验证了未命名命名空间与全局命名空间不能很好地混合的说法,解释了为什么你找不到 @987654331 @你已经定义了。

您还可以在Anonymous Namespace Ambiguity 中找到一些有用的信息。

【讨论】:

  • 经过一番调查,Seth 在上面的 cmets 中放入的内容让我相信,错误实际上是它实际构建的情况。所以没什么新东西,但我认为这个答案最接近问题的简短解释。
【解决方案2】:

问题在于&lt;functional&gt; 还从tupleutility 中提取了几个干扰查找的模板。

如果您要删除它,例如通过仅在 GCC 中包含 &lt;bits/stl_function.h&gt; 就没有问题,尽管这当然不是一个真正的解决方案。我想如果您需要谓词,您将无法实现自己的operator!=() 或为std::not_equal_to 添加显式特化。

但是,如果您不需要使用 not_equal_to 谓词,则可以通过删除所有自定义代码并添加以下内容来完全规避该问题:

#include <utility>
using namespace std::rel_ops;

bool test = a != a;

【讨论】:

  • 那为什么如果我没有手动创建这个模板我会得到“!=是非法操作”?问题源于默认情况下没有此模板的问题(我有一个只定义了 operator== 的类)。除此之外,我的未命名命名空间应该被忽略,应该使用来自 bits/stl_relops.h 的那个,不是吗?
  • 对不起,我的论点是错误的。它实际上是一组不同的模板进行干扰。但是,您只需将using namespace std::rel_ops; 添加到您的代码(来自&lt;utility&gt;)即可利用预定义的rel_ops
猜你喜欢
  • 2022-01-06
  • 2014-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-01
  • 1970-01-01
  • 2013-04-12
  • 2010-10-20
相关资源
最近更新 更多