为啥 range-v3 将其函数对象放入内联命名空间?

Posted

技术标签:

【中文标题】为啥 range-v3 将其函数对象放入内联命名空间?【英文标题】:Why does range-v3 put its function objects into an inline namespace?为什么 range-v3 将其函数对象放入内联命名空间? 【发布时间】:2018-10-05 05:03:05 【问题描述】:

在 range-v3 中,所有函数实际上都是 inline namespace 中的全局函数对象:

#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 命名空间的用途是什么?据我所知,图书馆的其他任何地方都没有引用它。

【问题讨论】:

可能与链接有关,就像 libc++ 的 std::__1 命名空间一样。 This is the PR 添加了此代码。也许comments that CaseyCarter made 可以对此有所了解 【参考方案1】:

基于 Casey 在 PR 上的 cmets 导致了这个添加(感谢 Justin),inline namespace 是这样的工作所必需的:

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#1)不在其自己的命名空间中,则 cpo 和为类型 friend 声明的非成员 friend(在 @ 987654330@)。这些必须位于不同的名称空间中。

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

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

【讨论】:

有一些讨论 on the Core reflector 从当我说服自己我们打破 [basic.scope.declarative]/4 后问这是否合法时。 (TLDR:内联命名空间使其合法。)

以上是关于为啥 range-v3 将其函数对象放入内联命名空间?的主要内容,如果未能解决你的问题,请参考以下文章

为啥内联未命名的命名空间?

为啥我不能内联调用 res.json?

超详细的C++入门学习(命名空间,缺省参数,内联函数,函数重载等)

即使放入标头c ++也无法内联函数

在容器上迭代地应用 range-v3 views::filter

为啥 C++ 中的 main() 不能内联?