2010-02-05 2 views
12

Я хотел бы определить бинарный оператор в глобальном пространстве имен. Оператор работает над классом, который определен в другом пространстве имен, и оператор должен получить доступ к частным членам этого класса. Проблема в том, что я не знаю, как охватить этот глобальный оператор, сделав его другом в определении класса.Как определить друзей в глобальном пространстве имен в другом пространстве имен C++?

Я пытался что-то вроде:

namespace NAME 
{ 
    class A { 
     public: 
      friend A ::operator * (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

A operator * (double lhs, const A& rhs) 
{ 
    double x = rhs.private_var; 
    ... 
} 

компилятор (г ++ 4.4) не знал, что делать с ним. Кажется, что линия

friend A ::operator *() 

оценивается как нечто вроде (псевдо-код)

(A::operator) 

вместо

(A) (::operator) 

Если я выхожу из :: в объявлении из оператор компиляции работает, но оператор находится в пространстве имен NAME, а не в глобальном пространстве имен.

Как я могу квалифицировать глобальное пространство имен в такой ситуации?

ответ

15

Во-первых, обратите внимание, что ваша декларация оператора недоставало квалификации пространства имен A:

NAME::A operator * (double lhs, const NAME::A& rhs) 

, а затем решающий Хитрость заключается в том, чтобы добавить скобки к другу декларации, как это, так же, как вы предложили в своем «псевдо -кода»

friend A (::operator *) (double lhs, const A& rhs); 

Для того, чтобы все это собрать, затем нужно несколько вперед заявлений, прибывающих на это:

namespace NAME 
{ 
    class A; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs); 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator *) (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs) 
{ 
    double x = rhs.private_var; 
} 

Александр прав, однако - вы должны, вероятно, объявить оператор в том же пространстве имен, что и его параметры.

+0

Это 3 почти идентичные ответы сейчас :-) – finnw

+0

Конечно, вы имеете в виду * только * три :) – 2010-02-05 14:38:26

3

Не знаю, какой именно ответ на ваш вопрос.

Но ужасно плохой идеей определить оператор за пределами пространства имен его параметров (теперь вы сокращаете зависимый от аргумента поиск, который очень удобен для операторов).

+2

+1. Хотя этот ответ сокращается до корня проблемы, один незначительный nitpick: если op * находится в глобальной области, то вам не нужен ADL, поскольку функция всегда доступна. (Я не уверен, но, может быть, OP не понимал ADL и, таким образом, придумал это?) – 2010-02-05 13:55:52

4

Это компиляция, я предполагаю, что без проверки, что она также работает. Обратите внимание на использование скобок:

namespace NAME {class A; } 
NAME::A operator * (double lhs, const NAME::A& rhs); 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator *) (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs) 
{ 
    double x = rhs.private_var; 
    return rhs; 
} 

int main() {} 

Как отмечает Александр, хотя, ваш вопрос не объясняет, почему оператор не в пространстве имен NAME. В любом случае его можно назвать 1.0 * some_A_instance. Таким образом, вы можете создать ненужную проблему для себя.

+0

Дарн, ты избил меня до 20 секунд. Почти идентичный код тоже. – finnw

+0

Это делает нас тремя сейчас, я думаю ... –

+0

Отлично, вы спасли мой день. Я не знал о том, что оператор может проживать в NAME и все еще работать так, как я хотел. – Andreas

2

Это возможно - вы можете заключить описатель в скобках: friend A (::operator * (double lhs, const A& rhs));

Вы также должны направить-объявить как класс и функцию.

namespace NAME {class A;} 
NAME::A operator *(double lhs, const NAME::A& rhs); 

// ... 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator * (double lhs, const A& rhs)); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator *(double lhs, const NAME::A& rhs) { 
    //... 
} 

Но я согласен с Андреасом в том, что было бы лучше определить как в том же пространстве имен, если это возможно.

Смежные вопросы