重载分辨率从幻数到int或long(在范围-v3中)

Ram*_*hoi 4 c++ c++11 c++14 range-v3

在range-v3中,view_facade类具有begin()功能.

template<typename D = Derived, CONCEPT_REQUIRES_(Same<D, Derived>())>
detail::facade_iterator_t<D> begin()
{
    return {range_access::begin_cursor(derived(), 42)};
}
Run Code Online (Sandbox Code Playgroud)

range_access::begin_cursor()是实现的,

template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto begin_cursor(Rng & rng, long) // --1
RANGES_DECLTYPE_AUTO_RETURN
(
    rng.begin_cursor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto begin_cursor(Rng & rng, int) // --2
RANGES_DECLTYPE_AUTO_RETURN
(
    static_cast<Rng const &>(rng).begin_cursor()
)
Run Code Online (Sandbox Code Playgroud)

在我的VS中,它看起来总是调用第二个函数.

我想知道什么时候将幻数(42)转换为long调用第一个函数.

Pio*_*cki 6

鉴于此RANGES_DECLTYPE_AUTO_RETURN 定义为:

#define RANGES_DECLTYPE_AUTO_RETURN(...)                        \
    -> decltype(__VA_ARGS__)                                    \
    { return (__VA_ARGS__); }                                   \
    /**/
Run Code Online (Sandbox Code Playgroud)

那么你的两个重载(在宏扩展之后)变成:

template<typename Rng>
static auto begin_cursor(Rng & rng, long) // --1
    -> decltype(rng.begin_cursor())
{
    return rng.begin_cursor()
}

template<typename Rng>
static auto begin_cursor(Rng & rng, int) // --2
    -> decltype(static_cast<Rng const &>(rng).begin_cursor())
{
    return static_cast<Rng const &>(rng).begin_cursor();
}
Run Code Online (Sandbox Code Playgroud)

begin_cursor使用int参数调用时,重载决策会找到完全匹配,这是第二个重载.最好是long,因为这需要转换参数表达式.但是,如果static_cast<Rng const &>(rng).begin_cursor()无效,即当成员函数begin_cursor()不是const限定时,decltype说明符内的表达式将触发替换失败,因此,编译器将继续搜索另一个重载,然后回退到第一个函数.