为什么adl更喜欢' boost :: range_detail :: operator |'在本地'运营商|'?

时间:2017-01-11 15:34:41

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

我试图为我的模板类operator|编写boo,一切正常,直到模板类是一个提升范围类型 - 就像示例中的{{1} } - adl优先于本地boost::range::filter_range

有人可以解释为什么adl更倾向于通过本地命名空间来提升这个详细命名空间的重载吗?

boost::range_detail::operator|(SinglePassRange& r, const replace_holder<T>)

}

clang错误(msvc报告几乎相同):

#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;
    }

1 个答案:

答案 0 :(得分:2)

根据ADL的规则, 集合中为boo<decltype(filtered)>{} | xs的重载添加的名称空间和类是local(对于boo),boost::range_detail(对于decltype(filtered))和stdstd::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之前。