简体   繁体   English

如何在另一个C ++命名空间中的全局命名空间中定义朋友?

[英]How do I define friends in global namespace within another C++ namespace?

I'd like to define a binary operator on in the global namespace. 我想在全局命名空间中定义二元运算符。 The operator works on a class that is defined in another namespace and the operator should get access to the private members of that class. 运算符处理在另一个名称空间中定义的类,并且运算符应该可以访问该类的私有成员。 The problem I have is that I don't know how to scope that global operator when making it a friend in the class definition. 我遇到的问题是,当我在类定义中将它作为朋友时,我不知道如何扩展该全局运算符的范围。

I tried something like: 我尝试过类似的东西:

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

The compiler (g++ 4.4) didn't know what to do with it. 编译器(g ++ 4.4)不知道如何处理它。 It seems that the line 看来就行了

friend A ::operator * ()

is evaluated as something like (pseudo-code) 被评估为(伪代码)

(A::operator)

instead of 代替

(A) (::operator)

If I leave out the :: in the declaration of the operator the compiling works but the operator is then in namespace NAME and not in the global namespace. 如果我在运算符的声明中省略了::编译工作,但运算符在命名空间NAME中而不在全局命名空间中。

How can I qualify the global namespace in such a situation? 在这种情况下,如何限定全局命名空间?

First, note that your operator declaration was lacking a namespace qualification for A: 首先,请注意您的运算符声明缺少A的名称空间限定:

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

and then the decisive trick is to add parentheses to the friend declaration like this, just as you proposed in your "pseudo-code" 然后决定性的把戏就是像这样在朋友声明中添加括号,就像你在“伪代码”中提出的那样

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

To make it all compile, you then need some forward declarations, arriving at this: 为了使它全部编译,你需要一些前向声明,到达这个:

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

Alexander is right, though -- you should probably declare the operator in the same namespace as its parameters. 但亚历山大是对的 - 您应该将运算符声明为与其参数相同的名称空间。

This compiles, I assume without testing that it also works. 这个编译,我假设没有测试它也有效。 Note the use of parentheses: 注意使用括号:

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() {}

As Alexander mentions, though, your question doesn't explain why the operator isn't in namespace NAME. 正如亚历山大提到的那样,你的问题并没有解释为什么运算符不在命名空间NAME中。 Either way it can be called as 1.0 * some_A_instance . 无论哪种方式,它都可以被称为1.0 * some_A_instance So you may be creating needless trouble for yourself. 所以你可能会为自己制造不必要的麻烦。

I don't know exact answer to your question. 我不知道你问题的确切答案。

But it's terrible bad idea to define operator outside namespace of its parameters (now you cut argument dependent lookup which is very usable for operators). 但是,在其参数的名称空间中定义运算符是一个糟糕的坏主意(现在你切断了对于运算符非常有用的参数依赖查找)。

It is possible - you can enclose the declarator in parentheses: friend A (::operator * (double lhs, const A& rhs)); 有可能 - 您可以将声明friend A (::operator * (double lhs, const A& rhs));括在括号中: friend A (::operator * (double lhs, const A& rhs));

You also need to forward-declare both the class and the function. 您还需要向前声明类和函数。

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) {
  //...
}

But I agree with Andreas that it would be better to define both in the same namespace if possible. 但我同意Andreas的观点,如果可能的话,最好在同一个命名空间中定义它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM