【问题标题】:namespace, class member ADL conflict命名空间、类成员 ADL 冲突
【发布时间】:2014-04-30 08:40:24
【问题描述】:
#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);
}

有没有办法限定打印函数以便打印基成员和派生成员?我可以将两个友元函数移动到它们最近的封闭命名空间:

#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&amp;) 击败了下面的静态演员建议,https://stackoverflow.com/a/22585103/710408。还有其他选择吗?

【问题讨论】:

    标签: c++ argument-dependent-lookup friend-function


    【解决方案1】:

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

    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
    

    【讨论】:

    • 这很好,也感谢您的链接。我有点不公平地添加了一个同名的成员,击败了静态演员......有什么想法吗?
    • 那么你需要使用第二个例子。您不能在类定义中使用 ADL 和友元函数,因为他首先找到成员函数(它在同一范围内定义)。 ADL 旨在解决来自不同命名空间的冲突,而不是来自同一类的冲突。该成员类的替代更改名称。
    【解决方案2】:

    你的意思是:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-01
      • 2021-11-22
      • 2010-09-20
      • 2013-01-26
      • 2010-11-15
      相关资源
      最近更新 更多