Как я определяю друзей в глобальном пространстве имен в другом пространстве имен 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;
    ...
}

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

friend A ::operator * ()

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

(A::operator)

вместо

(A) (::operator)

Если я не учитываю:: в объявлении оператора работы компиляции, но оператор находится тогда на ИМЯ пространства имен а не на глобальное пространство имен.

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

13
задан Andreas 5 February 2010 в 12:45
поделиться

4 ответа

Во-первых, обратите внимание, что в вашем объявлении оператора отсутствовала квалификация пространства имен для 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;
}

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

15
ответ дан 1 December 2019 в 21:52
поделиться

План выполнения показывает, что он действительно выполняется дважды. Но это выполняется только в том случае, если функция не является детерминированной . Для того чтобы функция была детерминированной, она должна быть определена опцией WITH SCHEMABINDING , и все функции, которые она вызывает, также должны быть детерминированными. После того, как я определил хеш-функцию как детерминированную, план изменился. Теперь он исполняется только один раз!

Однако, если вы не хотите беспокоиться об этом, решение momobo также работает.

-121--4293857-

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

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. Таким образом, вы можете создавать ненужные проблемы для себя.

-121--2681527-

Возможно - можно заключить декларатор в скобки: 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) {
  //...
}

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

2
ответ дан 1 December 2019 в 21:52
поделиться

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

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 . Так что вы можете создавать себе ненужные проблемы.

4
ответ дан 1 December 2019 в 21:52
поделиться

Я не знаю точного ответа на ваш вопрос. .

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

3
ответ дан 1 December 2019 в 21:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: