首页 > 解决方案 > 运算符 << 依赖于参数的查找不在全局命名空间中查找

问题描述

在以下场景中,在 function() 内部,在线ss << bb出现错误:

二进制“<<”:未找到采用“CommonType”类型右侧操作数的运算符(或没有可接受的转换)错误。

我的 ADL 理解是,它将查看当前的命名空间(即AppNamespace::InnerNamespace),并且由于没有operator <<找到,它将查看参数的命名空间,并且CommonType在全局命名空间中,我希望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;
}

CommonTypes.h:

    #pragma once

#include <vector>

typedef std::vector<uint8_t> CommonType;

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

标签: c++namespacesoperator-overloadingargument-dependent-lookup

解决方案


我的 ADL 理解是它将查看当前命名空间(即AppNamespace::InnerNamespace),并且由于没有找到 << 运算符,它会查看namespace参数CommonType的要找到的 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;
    }
    

推荐阅读