Безымянное пространство имен и iostream приводят к тому, что "! = Является незаконной операцией" - PullRequest
2 голосов
/ 13 декабря 2011
#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 Compiler) с:

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 <iostream>, она компилируется и работает просто отлично. Кто-нибудь осмелится объяснить это?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2011

Проблема в том, что <functional> также получает несколько шаблонов из tuple и utility, которые мешают поиску.

Если вы удалили это, например, включив только <bits/stl_function.h>в GCC проблем нет, хотя это, конечно, не реальное решение.Я полагаю, что вы не можете обойти ни реализацию собственной operator!=(), ни добавление явной специализации для std::not_equal_to, если вам требуется предикат.

Однако, если вам не нужно использовать предикат not_equal_to,Вы можете полностью обойти проблему, удалив весь свой пользовательский код и добавив следующее:

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

bool test = a != a;
0 голосов
/ 13 декабря 2011

Согласно Comeau, это не законно в любом случае - тот факт, что компилятор создает его, когда вы не #include <iostream>, может быть реальной ошибкой, а не наоборот (или, по крайней мере, разногласия в интерпретации):

"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 include - если вы посмотрите на вывод препроцессора из g ++, он не сделал ничего хитрого, чтобы изменить порядок кода или любую подобную чепуху, и, конечно, iostream не определяет operator!= для A.

У меня нет удобной копии стандарта C ++, но эта ссылка от IBM, по крайней мере, подтверждает утверждение о том, что безымянные пространства имен плохо сочетаются с глобальным, объясняя, почемувы не можете найти operator!=, который вы определили.

Вы также можете найти некоторую полезную информацию в Анонимность двусмысленности имен .

...