Why is ADL not working with Boost.Range?

后端 未结 3 669
误落风尘
误落风尘 2021-01-11 10:43

Considering:

#include 
#include 
#include 

int main() {
    auto range = boost         


        
3条回答
  •  醉酒成梦
    2021-01-11 11:12

    In boost/range/end.hpp they explicitly block ADL by putting end in a range_adl_barrier namespace, then using namespace range_adl_barrier; to bring it into the boost namespace.

    As end is not actually from ::boost, but rather from ::boost::range_adl_barrier, it is not found by ADL.

    Their reasoning is described in boost/range/begin.hpp:

    // Use a ADL namespace barrier to avoid ambiguity with other unqualified
    // calls. This is particularly important with C++0x encouraging
    // unqualified calls to begin/end.

    no examples are given of where this causes a problem, so I can only theorize what they are talking about.

    Here is an example I have invented of how ADL can cause ambiguity:

    namespace foo {
      template
      void begin(T const&) {}
    }
    
    namespace bar {
      template
      void begin(T const&) {}
    
      struct bar_type {};
    }
    
    int main() {
      using foo::begin;
      begin( bar::bar_type{} );
    }
    

    live example. Both foo::begin and bar::begin are equally valid functions to call for the begin( bar::bar_type{} ) in that context.

    This could be what they are talking about. Their boost::begin and std::begin might be equally valid in a context where you have using std::begin on a type from boost. By putting it in a sub-namespace of boost, std::begin gets called (and works on ranges, naturally).

    If the begin in the namespace boost had been less generic, it would be preferred, but that isn't how they wrote it.

提交回复
热议问题