为什么此功能调用不拒绝不合适的过载?
考虑以下代码:
#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{};
,还有许多其他过载函数就像:
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)
我的问题是:
- std ::范围中排序函数的呼唤是最好的匹配功能,不是吗?为什么后来在STD中发现的这些功能会引起歧义,而不是由于Sfinae原则而被放弃?
- 如果
sort(a)
在我们引入命名空间std后可以看到std中的功能,那么根据a
的ADL,在第一个代码中不应该同样可见。 ?
Consider the following code:
#include<vector>
#include<ranges>
#include<algorithm>
//using namespace std;
using namespace std::ranges;
int main()
{
std::vector<int> a = {};
sort(a);
return 0;
}
It's running properly.
Obviously, it called this overload function(functor, strictly speaking):
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));
}
But after we introducing the namespace std, the function call became ambiguous(got compilation errors):
#include<vector>
#include<ranges>
#include<algorithm>
using namespace std;
using namespace std::ranges;
int main()
{
std::vector<int> a = {};
sort(a);
return 0;
}
In addition to the previous reloads
2045 | inline constexpr __sort_fn sort{};
, there are many other overload functions found in namespace std like:
template<class _ExecutionPolicy, class _RandomAccessIterator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> std::sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator)
and
template<class _RAIter, class _Compare> constexpr void std::sort(_RAIter, _RAIter, _Compare)
So my questions are:
- The call of sort functor in std::ranges is the best match function, isn't it? Why do these functions later found in std cause ambiguity, rather than being abandoned due to the SFINAE principle?
- If the functions in std are visible for
sort(a)
after we introduced the namespace std, shouldn't it be equally visible in the first code according to the ADL ofa
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是
std :: ranges :: Sort
实际上不是函数模板。它是一些具有特殊名称查找属性的可叫实体,有时称为a niebloid 。结果,它的行为不像名称查找中的函数(模板)。您将两个
std :: Ranges :: Sort
和std :: sort
以通常的不合格的名称查找找到。std :: sort
是一个函数(模板),但是std :: ranges :: sort
不是。如果不合格的名称查找找到了多个实体,而不是所有实体都是函数或功能模板,则名称查找模棱两可,并且程序通常不构建。
那就是这里发生的事情。
The problem is that
std::ranges::sort
is not actually a function template. It is some callable entity with special name lookup properties, sometimes called a niebloid. As a consequence it doesn't behave like a function (template) in name lookup.You imported both
std::ranges::sort
andstd::sort
to be found by usual unqualified name lookup.std::sort
is a function (template), butstd::ranges::sort
isn't.If unqualified name lookup finds multiple entities and not all of them are functions or function templates, then the name lookup is ambiguous and the program usually ill-formed.
That is what is happening here.
问题是
std :: ranges :: Sort
是作为函数对象而不是函数实现的。来自 name lookup 规则:std :: Ranges :: Sort
是一个变量,因此名称查找失败(因为有多个声明匹配名称sort
)。和std :: ranges
算法被明确实现为函数对象(引用std :: ranges :: sort
cppReference ):因此,只要标准库实施
std :: ranges :: sort
作为函数对象(以及libstdc ++和libc ++似乎都这样做),就无法制作sort
name Lookup工作,如果您在全局名称空间中介绍了std :: ranges
和std
。The problem is that
std::ranges::sort
is implemented as function object and not a function. From name lookup rules:std::ranges::sort
is a variable, and thus name lookup fails (because there is more than one declaration matching namesort
). Andstd::ranges
algorithms are explicitly allowed to be implemented as function objects (quote fromstd::ranges::sort
cppreference):So, as long as standard library implements
std::ranges::sort
as function object (and both libstdc++ and libc++ seem to do that), there is no way to makesort
name lookup work if you introduce bothstd::ranges
andstd
in global namespace.