为什么 adl 更喜欢 'boost::range_detail::operator|' 而不是本地的 'operator|'?
Why is adl preferring the 'boost::range_detail::operator|' over the local 'operator|'?
我正在尝试为我的模板类编写一个operator|
boo
并且一切正常,直到模板类是提升范围类型 - 就像在示例中一样boost::range::filter_range
- adl 更喜欢boost::range_detail::operator|(SinglePassRange& r, const replace_holder<T>)
而不是本地。
谁能解释为什么 adl 更喜欢来自 boost 这个详细命名空间的重载而不是本地命名空间?
#include <vector>
#include <boost/range/adaptors.hpp>
namespace local
{
template<typename T>
struct boo {};
// this overload is not prefered when T is a boost::range::xxx_range
template<typename T, typename U>
auto operator|(boo<T>, U)
{
return false;
}
void finds_local_operator_overload()
{
std::vector<int> xs;
// works like expected and calls local::operator|
auto f = boo<decltype(xs)>{} | xs;
}
void prefers_boost_range_detail_replaced_operator_overload_instead_of_local_operator()
{
std::vector<int> xs;
// compiler error because it tries to call 'boost::range_detail::operator|'
auto filtered = xs | boost::adaptors::filtered([](auto &&x){ return x % 2; });
auto f = boo<decltype(filtered)>{} | xs;
}
}
CLANG 错误(MSVC 报告几乎相同):
/xxx/../../thirdparty/boost/1.60.0/dist/boost/range/value_type.hpp:26:70: error: no type named 'type' in
'boost::range_iterator<local::boo<boost::range_detail::filtered_range<(lambda at
/xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > >, void>'
struct range_value : iterator_value< typename range_iterator<T>::type >
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/xxx/../../thirdparty/boost/1.60.0/dist/boost/range/adaptor/replaced.hpp:122:40: note: in instantiation of template class
'boost::range_value<local::boo<boost::range_detail::filtered_range<(lambda at
/xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > > >' requested
here
BOOST_DEDUCED_TYPENAME range_value<SinglePassRange>::type>& f)
^
/xxx/Tests.cpp:222:37: note: while substituting deduced template arguments into
function template 'operator|' [with SinglePassRange = local::boo<boost::range_detail::filtered_range<(lambda at
/xxx/Tests.cpp:221:49), std::vector<int, std::allocator<int> > > >]
auto f = boo<decltype(filtered)>{} | xs;
根据 ADL 的规则, 在集合中添加的命名空间和类用于boo<decltype(filtered)>{} | xs
的重载是local
(对于boo
)、boost::range_detail
(对于decltype(filtered)
)和std
(对于std::vector<int>
xs
)。
我们特别有:
(如您所料,您的local
template<typename T, typename U> auto operator|(boo<T>, U);
和 )
boost::range_detail
中一个有问题的:
template <class SinglePassRange>
replaced_range<const SinglePassRange>
operator|(
const SinglePassRange&,
const replace_holder<typename range_value<SinglePassRange>::type>&);
所以我们有非推断range_value<boo<decltype(filtered)>>::type
,这会引起一个硬错误。(不幸的是,该方法对SFINAE不友好,无法从过载集中移除)。
错误发生在overload_resolution之前。
相关文章:
- 如果条件不相关,我应该更喜欢两个 if 语句而不是 if-else 语句吗?
- 为什么 C++ 程序员更喜欢前缀 ++,而 Java 程序员更喜欢后缀 ++?
- 在C++ Lambda 表达式中,为什么人们更喜欢按值捕获而不是作为参数传递?
- 如果可能的话,C++总是更喜欢右值引用转换运算符而不是常量左值引用吗?
- 为什么斯科特·迈耶斯(Scott Meyers)建议更喜欢"迭代器"而不是"const_i
- 在实现文件中,我们应该更喜欢"using namespace"指令还是将实现包装在命名空间 { } 中?
- 为什么 clang++ 更喜欢 adcx 而不是 adc
- 如何让编译器在C++中更喜欢常量方法重载?
- 为什么重载解析更喜欢不受约束的模板函数而不是更具体的模板函数?
- 使用LLVM在代码生成期间,更喜欢LLVM :: StringMap或STD :: MAP
- 我应该更喜欢在函数中的常数:constexpr const或enum
- 如何更喜欢由AddFontMemresourceex加载的字体而不是系统
- 明智的选择是更喜欢lambdas功能对象
- 有什么理由更喜欢从 IDE 中运行应用程序而不是运行独立的可执行文件?
- 为什么使用Mesos代码比遗产更喜欢模板
- Curly Braces构造函数更喜欢initializer_list而不是更好的匹配.为什么
- 非常量指针更喜欢常量 T&重载而不是常量 T*
- TensorFlow用户应该更喜欢SavedModel而不是Checkpoint或GraphDef吗?
- 我应该更喜欢 Rcpp::NumericVector 而不是 std::vector 吗?
- 为什么 adl 更喜欢 'boost::range_detail::operator|' 而不是本地的 'operator|'?