13

在 range-v3 中,所有函数都是内联命名空间中的真正全局函数对象:

#if RANGES_CXX_INLINE_VARIABLES < RANGES_CXX_INLINE_VARIABLES_17
#define RANGES_INLINE_VARIABLE(type, name)                              \
    inline namespace function_objects                                   \
    {                                                                   \
        inline namespace                                                \
        {                                                               \
            constexpr auto &name = ::ranges::static_const<type>::value; \
        }                                                               \
    }

#else  // RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
#define RANGES_INLINE_VARIABLE(type, name) \
    inline namespace function_objects      \
    {                                      \
        inline constexpr type name{};      \
    }
#endif // RANGES_CXX_INLINE_VARIABLES

命名空间的目的是什么function_objects?据我所知,图书馆的其他任何地方都没有引用它。

4

1 回答 1

12

根据 Casey 对导致此添加的PRinline namespace的评论(感谢 Justin),这样的事情需要这样做:

namespace N {
    namespace detail {
        // default implementation
        template <typename T> void swap(T&, T& ) { ... }

        struct swap_fn {
            template <typename T>
            void operator()(T& a, T& b) {
                swap(a, b); // unqualified call, the default is in scope
            }
        };
    }

    // the object
    inline namespace CPO { inline constexpr detail::swap_fn swap{}; } // #1

    struct S { friend void swap(S&, S&) { ... } }; // #2
}

N::S a;
N::swap(a, a); // calls the CPO, which calls the friend function

如果自定义点对象swap(at ) 不在其自己的命名空间中,则 cpo 和为类型(at )声明#1的非成员之间会出现名称冲突。这些必须位于不同的名称空间中。friendS#2

将 CPO 放在内联命名空间中就足够了,因为常规的不合格或合格查找永远不会找到交换位置#2- 它只会被 ADL 找到,这只会发生在swap_fn::operator().

是的,这很酷。并且复杂。

于 2018-04-24T21:51:50.093 回答