Я хотел бы определить бинарного оператора на в глобальном пространстве имен. Оператор работает над классом, который определяется в другом пространстве имен, и оператор должен получить доступ к членам парламента, не занимающим официального поста того класса. Проблема, которую я имею, состоит в том, что я не знаю, как определить объем того глобального оператора при создании этого другом в определении класса.
Я попробовал что-то как:
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)
Если я не учитываю:: в объявлении оператора работы компиляции, но оператор находится тогда на ИМЯ пространства имен а не на глобальное пространство имен.
Как я могу квалифицировать глобальное пространство имен в такой ситуации?
Во-первых, обратите внимание, что в вашем объявлении оператора отсутствовала квалификация пространства имен для 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;
}
Александр прав, однако - вы вероятно, следует объявить оператор в том же пространстве имен, что и его параметры.
План выполнения показывает, что он действительно выполняется дважды. Но это выполняется только в том случае, если функция не является детерминированной . Для того чтобы функция была детерминированной, она должна быть определена опцией 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
. Таким образом, вы можете создавать ненужные проблемы для себя.
Возможно - можно заключить декларатор в скобки: 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) {
//...
}
Но я согласен с Андреасом, что было бы лучше определить оба в одном пространстве имен, если это возможно.
Это компилируется, я предполагаю без тестирования, что он также работает. Обратите внимание на использование круглых скобок:
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
. Так что вы можете создавать себе ненужные проблемы.
Я не знаю точного ответа на ваш вопрос. .
Но это ужасно плохая идея определять оператор вне пространства имен его параметров (теперь вы отключили поиск, зависящий от аргументов, что очень удобно для операторов).