1

我發現這個有趣的一點在Boost.Range爲什麼Boost.Range range_begin/end free函數爲const和非const引用都重載?

在提供free-standing functions range_begin/end(), the docs state that

... range_begin()range_end()必須重載兩個constmutable參考參數。

事實上,在end.hpp看着它們的默認值,我們可以看到:

////////////////////////////////////////////////////////////////////// 
    // 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類型。

爲什麼我們首先需要過載?它是否使ADL工作?

回答

3

您顯然需要const &版本,否則您的range_begin將不可用於const限定對象。

不太明顯的是爲什麼你還需要&版本,但很簡單:如果你不提供它,那麼你的自定義函數比Boost自己的版本更差。

這裏的一個短的非升壓例如:

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

這裏,N::g<M::S>實例化期間,不合格的呼叫f(t)製成,和參數t具有類型M::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

相關問題