如何使std :: sort与std :: swap和命名空间的模板交换之间没有名称冲突?

时间:2018-10-25 22:05:32

标签: c++ namespaces overload-resolution ambiguous-call

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

我知道它是模棱两可的,因为my::swapmy::Obj位于同一命名空间中,而且我不在乎使用哪个版本的swap。我只需要克服名称空间冲突。这是我不拥有的非常庞大的代码库的一部分,因此我希望找到一种对我的代码而言本地的解决方案,并且可能允许my::Objmy::swap都保留在命名空间{{ 1}}。

my

3 个答案:

答案 0 :(得分:2)

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

 <property>
       <name>yarn.application.classpath</name>
       <value>
            %HADOOP_HOME%\etc\hadoop,
            %HADOOP_HOME%\share\hadoop\common\*,
            %HADOOP_HOME%\share\hadoop\common\lib\*,
            %HADOOP_HOME%\share\hadoop\hdfs\*,
            %HADOOP_HOME%\share\hadoop\hdfs\lib\*,
            %HADOOP_HOME%\share\hadoop\mapreduce\*,
            %HADOOP_HOME%\share\hadoop\mapreduce\lib\*,
            %HADOOP_HOME%\share\hadoop\yarn\*,
            %HADOOP_HOME%\share\hadoop\yarn\lib\*
       </value>
    </property>

然后,在3个有效的重载之间,都是完全匹配的,但首选 non -模板。

答案 1 :(得分:1)

与某些评论相反,有些令人惊讶的是,在没有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仅在自定义{{ 1}}是更好的候选者,假定使用自定义swap函数。

Jarod42显示的解决方案是定义更好的候选swap函数。

答案 2 :(得分:-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;
}