命名空间,类成员ADL冲突

namespace, class member ADL conflict

本文关键字:ADL 冲突 成员 命名空间      更新时间:2023-10-16
#include <iostream>
namespace outside {
  struct A { 
    int outer = 42; 
    friend void print(A const& a, std::ostream& os) 
    { os << "outside::A " << a.outer << 'n'; }
  };
  namespace inside {
    struct A : outside::A { 
      int inner = 24; 
      void print(std::ostream& os) { } // Added for extra difficulty
      friend void print(A const& a, std::ostream& os) { 
        // outside::A::print(a, os); // <- does not compile
        os << " inside::A " << a.inner << 'n'; 
      }
    };
  } // inside
} // outside
int main(int argc, char *argv[]) {
  outside::A a_outside;
  outside::inside::A a_inside;
  print(a_outside, std::cout);
  print(a_inside, std::cout);
}

是否有一种方法可以限定print函数,以便同时打印基成员和派生成员?我可以将这两个友元函数移到它们最近的封闭命名空间中:

#include <iostream>
namespace outside {
  struct A { int outer = 42; };
  void print(A const& a, std::ostream& os) 
  { os << "outside::A " << a.outer << 'n'; }
  namespace inside {
    struct A : outside::A { 
      void print(std::ostream& os) { } // Added for extra difficulty
      int inner = 24;
    };
    void print(A const& a, std::ostream& os) { 
      outside::print(a, os); // <- works
      os << " inside::A " << a.inner << 'n'; 
    }
  } // inside
} // outside
int main(int argc, char *argv[]) {
  outside::A a_outside;
  outside::inside::A a_inside;
  print(a_outside, std::cout);
  print(a_inside, std::cout);
}

成功了,结果如下:

outside::A 42 outside::A 42 inside::A 24

同样可以用好友函数实现吗?也许用using ?

编辑:inside::A::print(std::ostream&)击败静态cast建议如下,https://stackoverflow.com/a/22585103/710408。还有其他选择吗?

我找到了可能的解决方案:

friend void print(A const& a, std::ostream& os) { 
    print(static_cast<const outside::A&>(a), os);
    os << " inside::A " << a.inner << 'n'; 
}

一些信息为什么这个不工作:https://stackoverflow.com/a/382077/1938348结论很简单,当你在类体中定义friend函数时,它是不可见的,除非你使用ADL。要使它像你期望的那样工作,你需要改变声明的位置:

namespace outside {
  struct A { 
    int outer = 42; 
    friend void print(A const& a, std::ostream& os);
  };
  void print(A const& a, std::ostream& os) {
    os << "outside::A " << a.outer << 'n';
  }
  namespace inside {
    struct A : outside::A { 
      int inner = 24; 
      friend void print(A const& a, std::ostream& os);
    };
    void print(A const& a, std::ostream& os) { 
      outside::print(a, os);
      os << " inside::A " << a.inner << 'n'; 
    }
  } // inside
} // outside

你的意思是:

  friend void print(A const& a, std::ostream& os) { 
    // outside::A::print(a, os);
    print(static_cast<const outside::A&>(a), os);
    os << " inside::A " << a.inner << 'n'; 
  }