运算符<<依赖于参数的查找不会查找全局命名空间

时间:2018-05-09 15:50:31

标签: c++ namespaces operator-overloading argument-dependent-lookup

在以下场景中,在函数()内部ss << bb,我收到一个错误:

  

binary'&lt;&lt;':找不到带有'CommonType'类型(或没有可接受的转换)错误的右手操作数的运算符。

我的ADL理解是它会查看当前的命名空间(即AppNamespace::InnerNamespace)并且由于找不到operator <<,它将查看参数的命名空间并作为{{1在全局命名空间中,我希望找到CommonTypes.h中定义的CommonType。 显然我的理解是错误的。任何人都可以弄清楚这应该如何工作?

Main.cpp的

operator <<

CommonTypes.h:

namespace AppNamespace
{

    typedef std::vector<std::string> OtherType;

    std::ostream& operator << (std::ostream& os, const OtherType& ot)
    {
        for (auto& el : ot)
        {
            os << el;
        }
        return os;
    }

    namespace InnerNamespace
    {
        void function()
        {
            CommonType bb;
            std::stringstream ss;
            ss << bb;
        }
    }
}


int main()
{
    AppNamespace::InnerNamespace::function();
    return 0;
}

3 个答案:

答案 0 :(得分:1)

这里的问题是ADL查找将在std命名空间和命名空间中执行,其中声明CommonType是不相关的,因此为了使这项工作,您需要放置运算符&lt;&lt;在适当的命名空间中:

namespace std
{

ostream& operator << (ostream& os, const CommonType& bb)
{
    for (auto& el : bb)
    {
        os << el;
    }
    return os;
}

}

答案 1 :(得分:1)

  

我的ADL理解是它会查看当前的命名空间(即AppNamespace::InnerNamespace),因为没有&lt;&lt;找到运算符,它将查看参数的namespace,并且CommonType在全局命名空间中,我希望&lt;&lt;在CommonTypes.h中定义的运算符。

误解是CommonType是一种新类型。它不是一种新型的。这只是一个别名。

您可以使用各种方法解决函数查找问题。

  1. 在全局命名空间中定义operator<<个函数。

    #include <string>
    #include <sstream>
    #include <iostream>
    #include <vector>
    #include <cstdint>
    
    // Put everything from CommonTypes.h here to simplify things.
    typedef std::vector<uint8_t> CommonType;
    
    std::ostream& operator<<(std::ostream& os, CommonType const& bb)
    {
       for (auto& el : bb)
       {
          os << el;
       }
       return os;
    }
    
    namespace AppNamespace
    {
        typedef std::vector<std::string> OtherType;
    }
    
    std::ostream& operator << (std::ostream& os, const AppNamespace::OtherType& ot)
    {
       for (auto& el : ot)
       {
          os << el;
       }
       return os;
    }
    
    namespace AppNamespace
    {
       namespace InnerNamespace
       {
          void function()
          {
             CommonType bb;
             std::stringstream ss;
             ss << bb;
          }
       }
    }
    
    
    int main()
    {
       AppNamespace::InnerNamespace::function();
       return 0;
    }
    
  2. operator<<命名空间中定义AppNamespace个函数。

    #include <iostream>
    #include <vector>
    #include <cstdint>
    
    // Put everything from CommonTypes.h here to simplify things.
    typedef std::vector<uint8_t> CommonType;
    
    namespace AppNamespace
    {
       std::ostream& operator<<(std::ostream& os, CommonType const& bb)
       {
          for (auto& el : bb)
          {
             os << el;
          }
          return os;
       }
    
       typedef std::vector<std::string> OtherType;
       std::ostream& operator << (std::ostream& os, const OtherType& ot)
       {
          for (auto& el : ot)
          {
             os << el;
          }
          return os;
       }
    
       namespace InnerNamespace
       {
          void function()
          {
             CommonType bb;
             std::stringstream ss;
             ss << bb;
          }
       }
    }
    
    
    int main()
    {
       AppNamespace::InnerNamespace::function();
       return 0;
    }
    
  3. 在另一个命名空间中定义std::ostream& operator<<(std::ostream& os, CommonType const& bb)并明确将该函数放入AppNamespace的范围内。

    #include <string>
    #include <sstream>
    #include <iostream>
    #include <vector>
    #include <cstdint>
    
    // Put everything from CommonTypes.h here to simplify things.
    typedef std::vector<uint8_t> CommonType;
    
    namespace CommonNamespace
    {
       std::ostream& operator<<(std::ostream& os, CommonType const& bb)
       {
          for (auto& el : bb)
          {
             os << el;
          }
          return os;
       }
    }
    
    namespace AppNamespace
    {
       // Bring the operator<< functions in CommonNamespace into the scope of
       // this namespace.
       using CommonNamespace::operator<<;
    
       typedef std::vector<std::string> OtherType;
       std::ostream& operator << (std::ostream& os, const OtherType& ot)
       {
          for (auto& el : ot)
          {
             os << el;
          }
          return os;
       }
    
       namespace InnerNamespace
       {
          void function()
          {
             CommonType bb;
             std::stringstream ss;
             ss << bb;
          }
       }
    }
    
    
    int main()
    {
       AppNamespace::InnerNamespace::function();
       return 0;
    }
    

答案 2 :(得分:0)

如果您不想按照VTT的建议在std命名空间中移动运算符,则可以指定它位于全局命名空间中:

(::operator <<)(ss, bb);