簡體   English   中英

如何使std :: sort與std :: swap和命名空間的模板交換之間沒有名稱沖突?

[英]How do I make std::sort not have name collision between std::swap and my namespace's templated swap?

我想使用std::sort ,但是編譯失敗,錯誤C2668: std::swap: ambiguous call to overloaded function因為在我的命名空間中定義了一個模板化swap()函數,這很難擺脫。 我不在乎它使用哪個swap ,但是在編譯sort()時如何使其中任何一個消失?

我知道它是模棱兩可的,因為my::swapmy::Obj在同一個命名空間中,而且我不在乎使用哪個版本的swap 我只需要克服名稱空間沖突。 這是我不擁有的非常大的代碼庫的一部分,因此我希望找到一種對我的代碼而言本地的解決方案,並且可能允許my::Objmy::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是更好的候選者(自定義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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM