Я хочу использовать 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());
}
};
Обходной путь должен создать лучшую перегрузку:
// 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 допустимыми перегрузками, все точно совпадают, но не-Шаблон является предпочтительным.
Вопреки некоторым комментариям и удивительным для некоторых эта ошибка происходит без 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
функция.
Ты наверное 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;
}