2017-01-11 9 views
3

내 템플릿 클래스 boooperator|을 쓰려고하는데 템플릿 클래스가 부스트 범위 유형 (예 : boost::range::filter_range)에서와 같이 로컬 클래스에서 boost::range_detail::operator|(SinglePassRange& r, const replace_holder<T>)을 선호 할 때까지 모든 것이 잘 작동합니다.왜 adl은 'boost :: range_detail :: operator |'를 선호합니까? 로컬 '연산자'를 통해?

adl이 로컬 네임 스페이스보다 세부 네임 스페이스를 높여주는 오버로드를 선호하는 이유는 누구나 설명 할 수 있습니까?

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

}

연타 오류 (거의 같은 MSVC 보고서) : ADL의 규칙에 따르면

/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; 
+1

두 운영자 모두 고려해야합니다. 하지만 부스트가 더 전문적이라고 생각합니다. – Jarod42

+0

'boost :: range_detail :: replace_holder' 템플릿 함수를 고려하는 이유는 무엇입니까? boost 네임 스페이스를 여는 인수가 없습니다. 부스트 이름 공간의 템플리트 'T'만 있습니다. 그리고 그것을 고려해야 할 충분한 이유가 있다면 왜 다른 부스트 범위 홀더 템플릿 기능이 고려되지 않습니까? – TimW

답변

2

, boo<decltype(filtered)>{} | xs에 대한 과부하 세트에 추가 네임 스페이스와 클래스 local 있습니다 (boo), boost::range_detail (decltype(filtered)) 및 std()이있다.

우리는 특수성에 있습니다

(당신은 예상대로 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 전에 오류가 발생했습니다.

+0

'class template specialization'이라는 문서화 된 cppreference에는 다소 모호한 부분이있는 것처럼 보입니다.이 경우 'boo '은 분명히 전문 분야가 아니므로 _instantiation_ 클래스 템플릿입니다. – xtofl

+2

@xtofl 그것은 specailization을 명명하는 특수화 (물론, * simple-template-id *)이기 때문에 프로그램에서 사용하면 14.7.1 [temp.inst]에 따라 (암시 적) 인스턴스화가 발생할 수 있습니다. – Cubbi