C ++中的朋友名称解析范围

Friend name resolving scope in C++

这是遗留代码,可能在时代 3.2 或 2.8 g++ 中有效,但不再有效。它仍然在 Microsoft C/C++ 优化编译器 v.17 下编译。该代码也已从原始代码中删减以隔离突出问题。

in function +=, error: 'to_every' was not declared in this scope

class Matrix {};

class ElementWiseConst
{
public:
  ElementWiseConst(const Matrix& m){}
};

class ElementWise : public ElementWiseConst
{
public:
  ElementWise(const ElementWise&);
  ElementWise(Matrix& m) : ElementWiseConst(m) {}
  void operator +=  (const double val); 
  friend ElementWise to_every(Matrix& m) { return m; }
};

Matrix& operator += (Matrix& m, const double val) { 
  to_every(m) += val; 
  return m; 
}

这是否是 Microsoft 错误地允许的隐式转换或作用域?

to_every 定义在 ElementWise 内部,因此只能通过 ADL 找到。编译器将查看提供的参数并使用其关联的命名空间和 classes 来查找名称 to_everyMatrix 的关联 classes 是 Matrix 本身,其关联的命名空间是全局命名空间(假设它是在那里声明的)。 ElementWise 需要关联 class,因此找不到 to_every

要使其正常工作,您可以:

  • 在 class 之外定义 to_every

  • 使 ElementWise 成为关联的 class 通过使其成为模板参数 (@sehe):

    template<class T>
    class ADLMatrix {};
    
    using Matrix = ADLMatrix<class ElementWise>;