c++ - 为什么 adl 更喜欢 'boost::range_detail::operator|' 而不是本地 'operator|'?

标签 c++ argument-dependent-lookup boost-range

我正在尝试写一个 operator|对于我的模板类 boo并且一切正常,直到模板类是一个提升范围类型 - 如示例中的 boost::range::filter_range - adl 更喜欢 boost::range_detail::operator|(SinglePassRange& r, const replace_holder<T>)在本地。

谁能解释为什么 adl 更喜欢 boost this detailed namespace 而不是 local namespace 的重载?

#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 之前.

关于c++ - 为什么 adl 更喜欢 'boost::range_detail::operator|' 而不是本地 'operator|'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41594854/

相关文章:

c++ - "long"和 "long int"之间的区别,abs & labs

c++ - 在 C++ 中读取/写入设备

c++ - 为什么我能够在没有 std::qualifier 的情况下调用这个 C++ 标准库函数?

c++ - 友元函数的参数依赖查找

c++ - 使用 boost::range 在 C++ 中进行花式索引

c++ - Boost::Range 中的 itertools.tee 等效项?

c++ - 如何使用 boost::joined_range 实现范围适配器

C++11 - 可以等待几个不同事件的线程?

c++ - 从文件中读取对象时 undefined symbol

c++ - ADL 是否与命名的 lambda 一起使用?