Оператор << аргумент-зависимый поиск не ищет в глобальном пространстве имен - PullRequest
0 голосов
/ 09 мая 2018

В следующем сценарии внутри функции () в строке ss << bb я получаю сообщение об ошибке:

двоичное '<<': не найден оператор, который принимает правый операнд типа CommonType (или нет приемлемого преобразования). </p>

Мое понимание ADL состоит в том, что он будет изучать текущее пространство имен (то есть AppNamespace::InnerNamespace), и, поскольку operator << не найден, он будет изучать пространство имен аргументов, а CommonType находится в глобальном пространстве имен. Я ожидаю, что operator <<, определенный в CommonTypes.h, будет найден. Очевидно, мое понимание неверно. Кто-нибудь может понять, как это должно работать?

main.cpp

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

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Если вы не хотите перемещать своего оператора в пространство имен std, как рекомендует VTT, вы можете указать, что он находится в глобальном пространстве имен:

(::operator <<)(ss, bb);
0 голосов
/ 09 мая 2018

Мое понимание ADL состоит в том, что он будет изучать текущее пространство имен (то есть AppNamespace::InnerNamespace), и, поскольку оператор << не найден, он будет смотреть на <code>namespace аргументов, а CommonType находится в глобальное пространство имен Я ожидаю, что будет найден оператор <<, определенный в CommonTypes.h. </p>

Недоразумение в том, что 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;
    }
    
0 голосов
/ 09 мая 2018

Проблема здесь в том, что поиск ADL будет выполняться в std пространстве имен и пространстве имен, где объявлено CommonType, не имеет значения, поэтому для выполнения этой работы вам нужно поместить operator << в соответствующее пространство имен: </p>

namespace std
{

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

}
...