1

나는 Boost.Range이 흥미로운 비트를 발견Boost.Range range_begin/end free 함수가 const 및 non-const 참조 모두에 오버로드되는 이유는 무엇입니까?

free-standing functions range_begin/end(), the docs state that를 제공 할 때 :

... range_begin()range_end() 모두 constmutable 참조 인수 오버로드해야합니다.

////////////////////////////////////////////////////////////////////// 
    // pair 
    ////////////////////////////////////////////////////////////////////// 

    template< typename Iterator > 
    inline Iterator range_end(const std::pair<Iterator,Iterator>& p) 
    { 
     return p.second; 
    } 

    template< typename Iterator > 
    inline Iterator range_end(std::pair<Iterator,Iterator>& p) 
    { 
     return p.second; 
    } 

당신은주의 할 것이다 (그리고 example given in the docs는이 작업을 수행) 두 버전이 동일한 Iterator 형식을 반환하는 것이 :

그리고 실제로, end.hpp에 기본값을보고, 우리는 참조하십시오.

왜 우리는 처음에 두 가지 과부하가 필요합니까?ADL을 작동시키는가요?

답변

3

그렇지 않으면 range_begin이 const 한정 개체에 대해 호출 할 수 없으므로 분명히 const & 버전이 필요합니다.

& 버전이 필요하지 않은 이유는 분명하지 않지만 간단합니다. 제공하지 않으면 사용자 지정 함수가 Boost 자체 버전보다 나 빠지게됩니다.

가 여기에 짧은 비 부스트 예제 : N::g<M::S>의 인스턴스화하는 동안,

namespace M { 
    struct S { }; 
    void f(const S &); 
} 

namespace N { 
    template <typename T> 
    void f(T &); 

    template <typename T> 
    void g(T &t) { f(t); } 
} 

void h() { 
    M::S s {}; 
    N::g(s); 
} 

여기서, 적정 전화 f(t)이 이루어지며, 인수 tM::S을 입력있다. 두 후보가 있습니다. N::f<M::S>은 같은 네임 스페이스에 있지만 ADL도 M::f을 찾습니다. 전자의 매개 변수는 M::S &입니다. 후자는 const M::S &입니다. 이는 네임 스페이스 M의 버전을 실제로 사용하려는 경우에도 전자가 더 잘 일치 함을 의미합니다.

추가 과부하 M::f(S &)은이 문제를 방지합니다.

+0

예에서'M :: f'는 템플릿이 아닌 함수입니다. 이 점이 차이점이 있습니까? –

+0

@MartinBa'M :: f'에는'S &'와'const S &'버전이 모두있는 한 작동해야합니다. 이를 위해 템플리트에서 이러한 과부하를 사용할 수 있는지 여부는 중요하지 않습니다. – hvd