将operator "" (...)
定义为朋友功能是否可行和/或有用?
class Puzzle {
friend Puzzle operator "" _puzzle(const char*, size_t);
...
};
void solve(Puzzle);
int main() {
solve("oxo,xox"_puzzle);
};
我正在考虑“有用”,因为operator ""
仅应在命名空间中定义的规则 - 至少是因为以_
开头的标识符在全局命名空间中保留。这friend
是否打破了这条规则?所以,这种不完全封装没有任何好处,对吗?
答案 0 :(得分:2)
标准直接解决了这个问题,它提到了对用户定义文字声明的任何限制,§13.5.8/ 2:
声明者id是文字操作符id的声明应该是命名空间范围函数或函数模板的声明(它可以是友元函数(11.3)),一个显式函数模板的实例化或特化,或者使用声明(7.3.3)。
如果朋友也在命名空间范围内声明,那么类或命名空间范围中的定义之间没有区别。请注意,在命名空间范围内不需要定义,这是您当前提出的问题断言。
如果未在命名空间范围内声明,因为ADL无法找到它,所以可以通过常规非限定名称查找在该范围内私有地使用该朋友。这是声明不是外部接口的文字运算符的唯一方法。
如果朋友是在类模板中定义的,那么模板的两个实例将在命名空间范围内生成两个同名的函数,即使它们在类范围外都是不可见的,也会发生冲突。
答案 1 :(得分:1)
如果它有助于语法,下面是我在类中声明朋友用户定义的文字运算符的方式,其中运算符本身位于命名空间中:
class Integer;
namespace literals {
Integer operator "" _I (const char *);
}
// Infinite precision integer
class Integer {
public:
// Basic constructor & destructor
Integer ();
~Integer ();
... rest of the interface ...
// Literal operator
friend Integer literals::operator "" _I (const char *);
private:
struct Detail;
std::unique_ptr<Detail> detail;
};
用户只有在需要时才会使用using namespace literals;
语句提取运算符。 (实际上,所有这些都在父命名空间中,但你明白了。)
答案 2 :(得分:0)
根据标准,是的,朋友声明应该是合法的。 顺便说一句,该名称适用于用户代码,因为即使在全局命名空间中它也以下划线开头。
朋友声明将允许操作员访问类私有数据。
我开始质疑朋友文字运营商的用处。因为用户定义的运算符只能有一些参数列表,所以无法将类放在参数中。因此现在有依赖于参数查找的方法来找到正确的函数。我是对的吗?