1

我想使用std::sort,但编译失败并出现错误C2668: std::swap: ambiguous call to overloaded function,因为swap()在我的命名空间中定义了一个很难删除的模板化函数。我不在乎swap它使用哪个,但是在编译时如何使它们中的任何一个消失sort()

我知道这是模棱两可的,因为my::swap它与 位于相同的命名空间中my::Obj,而且我不在乎swap使用哪个版本。我只需要克服命名空间冲突。这是我不拥有的一个非常大的代码库的一部分,所以我希望有一个解决方案是我的代码本地的,并且可能允许my::Obj并且my::swap都保留在 namespace 中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());
    }
};
4

3 回答 3

2

一种解决方法是创建更好的重载:

// 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 个有效重载之间,所有重载都是完全匹配的,但首选非模板。

于 2018-10-26T00:09:22.210 回答
2

与一些评论相反,令一些人惊讶的是,这个错误在没有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函数。

于 2018-10-26T00:39:29.047 回答
-1

你大概是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;
}
于 2018-10-25T22:59:59.987 回答