C ++ 0x,用户定义的文字与朋友操作符“”()

时间:2011-09-09 07:06:24

标签: c++ c++11 friend-function user-defined-literals

operator "" (...)定义为朋友功能是否可行和/或有用?

class Puzzle {
  friend Puzzle operator "" _puzzle(const char*, size_t);
  ...
};
void solve(Puzzle);
int main() {
  solve("oxo,xox"_puzzle);
};

我正在考虑“有用”,因为operator ""仅应在命名空间中定义的规则 - 至少是因为以_开头的标识符在全局命名空间中保留。这friend是否打破了这条规则?所以,这种不完全封装没有任何好处,对吗?

3 个答案:

答案 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)

根据标准,是的,朋友声明应该是合法的。 顺便说一句,该名称适用于用户代码,因为即使在全局命名空间中它也以下划线开头。

朋友声明将允许操作员访问类私有数据。

我开始质疑朋友文字运营商的用处。因为用户定义的运算符只能有一些参数列表,所以无法将类放在参数中。因此现在有依赖于参数查找的方法来找到正确的函数。我是对的吗?