wehute
wehute

Reputation: 3

Friend name resolving scope in C++

This is legacy code that likely worked in era 3.2 or 2.8 g++, but no longer. It does still compile under microsoft C/C++ optimizing compiler v.17. The code has also been trimmed down from the original to isolate the salient issue.

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

Is this an implicit conversion or scoping that microsoft is incorrectly allowing?

Upvotes: 0

Views: 53

Answers (1)

David G
David G

Reputation: 96835

to_every is defined inside of ElementWise and thus can only be found via ADL. The compiler will look at the arguments provided and use its associated namespaces and classes to find the name to_every. The associate classes of Matrix is Matrix itself and its associated namespace is the global namespace (assuming it was declared there). ElementWise needs to be an associated class, thus to_every cannot be found.

To get this to work you can:

  • Define to_every outside of the class.

  • Make ElementWise an associated class by making it a template argument (@sehe):

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

Upvotes: 1

Related Questions