未命名的命名空间和 iostream 导致“!= 非法操作”

发布于 2024-12-20 21:01:05 字数 1200 浏览 1 评论 0原文

#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 它会编译并且运行得很好。有谁敢来解释一下吗?

#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;
}

This fails on CC (SunOs Compiler) with:

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.

And on g++ with:

/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'

However if I remove the line #include <iostream> it compiles and runs just fine. Anyone dare to explain this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无边思念无边月 2024-12-27 21:01:05

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

"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 至少验证了未命名命名空间不混合的说法与全局操作符一样好,解释了为什么找不到您定义的 operator!=

您还可能在匿名命名空间歧义中找到一些有用的信息。

According to Comeau, this isn't legal either way - the fact that the compiler builds it when you don't #include <iostream> may be the actual bug, not the other way around (or at least a disagreement in interpretation):

"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){
           ^

It makes sense that this doesn't build - placing operator!= in an unnamed namespace still puts it in a different namespace than ::, and I'm not entirely sure why g++ builds it without the iostream include - if you look at the preprocessor output from g++ it hasn't done anything hinky to reorder code or any such nonsense, and of course iostream doesn't define operator!= for A.

I do not have my copy of the C++ standard handy, but this link from IBM at least validates the claim that unnamed namespaces don't mix that well with the global one, explaining why you can't find the operator!= you've defined.

You also might find some helpful information in Anonymous Namespace Ambiguity.

飘过的浮云 2024-12-27 21:01:05

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

如果您要删除它,例如仅在 GCC 中包含 ,那么就没有问题,尽管这当然不是真正的解决方案。我想如果您需要谓词,您无法绕过实现您自己的 operator!=() 或添加 std::not_equal_to 的显式专业化。

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

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

bool test = a != a;

The problem is that <functional> also pulls in several templates from from tuple and utility that interfere with the lookup.

If you were to remove this, e.g. by only including <bits/stl_function.h> in GCC, then there is no problem, although is is of course not a real solution. I suppose you cannot get around either implementing your own operator!=() or adding an explicit specialization for std::not_equal_to if you require the predicate.

However, if you don't need to use the not_equal_to predicate, you can circumvent the problem entirely by removing all your custom code and adding the following:

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

bool test = a != a;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文