Как сделать так, чтобы в std :: sort не было конфликтов имен между std :: swap и шаблонным swap моего пространства имен? - PullRequest
0 голосов
/ 26 октября 2018

Я хочу использовать std::sort, но компиляция не удалась с ошибкой C2668: std::swap: ambiguous call to overloaded function, потому что в моем пространстве имен определена шаблонная функция swap(), от которой было бы трудно избавиться.Мне все равно, какой swap он использует, но как заставить один из них уйти при компиляции sort()?

Я понимаю, что это неоднозначно, потому что my::swap находится в том же пространстве имен, что иmy::Obj, и мне все равно, какая версия swap будет использоваться.Я просто должен преодолеть столкновение пространства имен.Это часть очень большой базы кода, которой я не владею, поэтому я надеюсь на решение, которое будет локальным для моего кода и предположительно позволит my::Obj и my::swap оставаться в пространстве имен my.

namespace my
{
    template<class T> void swap(T a, T b)
    {
    }

    struct Obj
    {
    };

    void doSortStuff()
    {
        std::vector<Obj> arr;
        std::sort(arr.begin(), arr.end());
    }
};

Ответы [ 3 ]

0 голосов
/ 26 октября 2018

Обходной путь должен создать лучшую перегрузку:

// No modifiable code
namespace my
{
    template<class T> void swap(T a, T b) { /*.. */ }
    struct Obj { /*..*/ };
}

// Your code:
namespace my
{
    void swap(Obj& lhs, Obj& rhs)
    {
        // my::swap<Obj&>(lhs, rhs);
        std::swap(lhs, rhs);
    }
}

// In namespace you want.
void doSortStuff()
{
    std::vector<my::Obj> arr;
    std::sort(arr.begin(), arr.end());
}

Затем, между 3 допустимыми перегрузками, все они точно совпадают, но предпочтительным является non - шаблон.

0 голосов
/ 26 октября 2018

Вопреки некоторым комментариям и удивительным для некоторых эта ошибка происходит без using namespace std.Вот минимальный пример, чтобы понять, что происходит:

namespace like_std
{
    template<class T> void swap(T a, T b) {}

    template <class T> auto test(T x, T y)
    {
        swap(x, y); // (1) ambiguous call
    }
}

namespace my
{
    template<class T> void swap(T a, T b) {}

    struct Obj {};

    void doStuff()
    {
        like_std::test(Obj{}, Obj{});
    }
};

Вы вызываете функцию из like_std, и внутри этой функции есть безусловный вызов swap.Для этого вызова:

  • like_std::swap является кандидатом, поскольку находится в том же пространстве имен, что и вызов swap

  • my::swapявляется кандидатом из-за ADL: он введен, потому что он находится в том же пространстве имен, что и один из аргументов для вызова swap

Поскольку ни один из них не является лучшим, возникает двусмысленность.

Причина, по которой вызов swap является неквалифицированным, заключается в том, что он выберет пользовательский swap, если он определен, , но , который работает, только если пользовательский swapявляется лучшим кандидатом, который предполагается для пользовательской функции swap.

Решение, показанное Jarod42 , заключается в определении лучшего кандидата swap функция.

0 голосов
/ 26 октября 2018

Вы, вероятно, using namespace std;.

. В этом случае компилятор не знает, что выбрать, поскольку он делает доступными все std:: члены, не вводя их автоматически, где подходят обе функции:

using namespace std;
swap(a, b); //your swap
swap(a, b); //std::swap

Как и в этом случае, у вас строгие вызовы функций:

std::swap(a, b); //from std
swap(a, b); // your one

На самом деле это очень хороший пример того, почему вам следует избегать using namespace std.Удачи!

Обновление: это может быть вашим решением - переместите swap() за пределы std::sort() использования:

#include <algorithm>
#include <vector>

namespace detail
{
  struct someContainer
  {
    someContainer(int &v)
    {
      value = v;
    }
    int value;
    someContainer &operator = (const someContainer & rhs)
    {
      this->value = rhs.value;
    }
    bool operator == (someContainer &rhs) const
    {
      return this->value == rhs.value;
    }
    bool operator <= (someContainer &rhs) const
    {
      return this->value <= rhs.value;
    }
    bool operator >= (someContainer &rhs) const
    {
      return this->value >= rhs.value;
    }
    bool operator > (someContainer &rhs) cosnt
    {
      return this->value > rhs.value;
    }
    bool operator < (someContainer &rhs) const
    {
      return this->value < rhs.value;
    }
  };
  void doSomeStuff()
  {
    std::vector<someContainer> vec;
    for (int i = 0; i < vec.size(); ++i)
    {
      vec.push_back(someContainer(i));
    }
    std::sort(vec.begin(), vec.end());
  }
}

namespace mySwap
{
  template< class T >
  void swap(T &a, T &b)
  {
     T c = a;
     a = b;
     b = c;
  }
}
int main()
{
  detail::doSomeStuff();
  return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...