[英]Why is this function call didn't reject the unsuitable overload?
考慮以下代碼:
#include<vector>
#include<ranges>
#include<algorithm>
//using namespace std;
using namespace std::ranges;
int main()
{
std::vector<int> a = {};
sort(a);
return 0;
}
它運行正常。
顯然,它調用了這個重載函數(嚴格來說,函子):
template<random_access_range _Range,
typename _Comp = ranges::less, typename _Proj = identity>
requires sortable<iterator_t<_Range>, _Comp, _Proj>
constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const
{
return (*this)(ranges::begin(__r), ranges::end(__r),
std::move(__comp), std::move(__proj));
}
但是在我們引入命名空間std之后,函數調用變得模棱兩可(編譯錯誤):
#include<vector>
#include<ranges>
#include<algorithm>
using namespace std;
using namespace std::ranges;
int main()
{
std::vector<int> a = {};
sort(a);
return 0;
}
除了之前的重裝
2045 | inline constexpr __sort_fn sort{};
,在命名空間 std 中還有許多其他重載函數,例如:
template<class _ExecutionPolicy, class _RandomAccessIterator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> std::sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator)
和
template<class _RAIter, class _Compare> constexpr void std::sort(_RAIter, _RAIter, _Compare)
所以我的問題是:
sort(a)
是可見的,那么根據a
的 ADL,它不應該在第一個代碼中同樣可見嗎?問題是std::ranges::sort
實際上不是函數模板。 它是一些具有特殊名稱查找屬性的可調用實體,有時稱為niebloid 。 因此,它在名稱查找中的行為不像函數(模板)。
您導入了std::ranges::sort
和std::sort
以通過通常的非限定名稱查找找到。 std::sort
是一個函數(模板),但std::ranges::sort
不是。
如果非限定名稱查找找到多個實體並且並非所有實體都是函數或函數模板,則名稱查找不明確並且程序通常格式錯誤。
這就是這里正在發生的事情。
問題是std::ranges::sort
被實現為函數對象而不是函數。 從名稱查找規則:
對於函數和函數模板名稱,名稱查找可以將多個聲明與同一個名稱相關聯,並且可以從依賴於參數的查找中獲取額外的聲明。 [...]
對於所有其他名稱(變量、命名空間、類等),名稱查找必須生成單個聲明才能編譯程序。
std::ranges::sort
是一個變量,因此名稱查找失敗(因為有多個聲明匹配名稱sort
)。 並且明確允許將std::ranges
算法實現為函數對象(引用std::ranges::sort
cppreference ):
本頁描述的類函數實體是niebloids ,即:[...]
在實踐中,它們可以實現為函數對象,或者具有特殊的編譯器擴展。
因此,只要標准庫將std::ranges::sort
實現為函數對象(libstdc++ 和 libc++ 似乎都這樣做),如果同時引入std::ranges
和std
,就無法進行sort
名稱查找在全局命名空間中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.