命名空间,类成员ADL冲突

时间:2014-03-22 23:09:01

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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

你的意思是:

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