C ++ 11内联命名空间vs直接在封闭命名空间中嵌入类型

时间:2017-04-14 23:57:23

标签: c++ c++11 namespaces

阅读和研究很多关于新的C ++ 11特性 - "内联命名空间"我不明白这个功能的真正好处是什么。

我可以很容易地拥有在"内联命名空间中定义的所有函数/类型"直接放在封闭的一个并具有相同的结果。 那么将函数/类型放在内联命名空间中的真正动机是什么? 分组功能/类型? 使用"内联命名空间"是否有任何与ADL相关的好处? 我认为ADL会表现得一样,因为有一个隐含的"使用"这个"内联命名空间的指令。"

EDIT1:

所以我认为以下是关键优势。 我们先说我们有这个:

namespace toplevel {
     // Users can use toplevel::MyType
     inline namespace current {
           class MyType {};
     } // inline namespace current
} // ns toplevel

现在,一些新的要求,我们需要一个新版本 可用但保持旧的完整:

namespace toplevel {
     // Users can use toplevel::MyType
     // we can let the users know that we are going to deprecate it
     // in favor of toplvel::next::MyType
     inline namespace current {
           class MyType {};
     } // inline namespace current

     // Users can use toplevel::next::MyType
     namespace next {
           class MyType {};
     } // namespace next

} // ns toplevel

最后这样做。内联移动到" next"命名空间 它是默认的。仍让用户访问"当前"但 with explicit :: current - 即这样:toplevel :: current :: MyType 顺便说一句 - 我的偏好甚至会重命名"当前" to"弃用"。

namespace toplevel {
     // Users can still use it by referring
     // to toplevel::current::MyType
     namespace current {
           class MyType {};
     } // inline namespace current

     // Have this one the default one 
     // under toplevel
     // Users can use the new one this way: toplevel::MyType
     inline namespace next {
           class MyType {};
     } // namespace next

} // ns toplevel

这听起来像是一个正确的场景吗?

1 个答案:

答案 0 :(得分:3)

C++ 内联命名空间的主要动机确实涉及版本控制。除了问题中的最后一句话,您的理解是正确的:

<块引用>

我的偏好甚至会将“当前”重命名为“已弃用”

使用内联命名空间的整个想法是命名空间名称不会改变——相反,这个特性允许命名空间名称​​不需要改变;现有名称可以永久存在,无需对代码进行大量更改。

相反,在发布版本时(当我们过去认为的“当前功能”现在变成“不推荐使用的功能”时),命名空间名称可以保持不变,但它们的默认状态会更新。

>

让我们在代码中看到这一点:

namespace MyProject {
    namespace Version1 {
        void BoringStableFunction() {...}
    }
    inline namespace Version2 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(int x) {...}
    }
}

该软件的客户可能最常通过调用 MyProject::BoringStableFunction()MyProject::LatestAndGreatest(11) 来使用它,甚至可能不知道存在两个单独的 MyProject 版本。这种便利可能是一件好事。如果客户确实知道有两个不同的版本,并且有意使用旧版本(在 LatestAndGreatest() 被发明之前),他仍然可以通过调用 MyProject::Version1::BoringStableFunction() 来实现。

请注意,允许客户端将其代码编写为 MyProject::Version2::BoringStableFunction()。这样做实际上是客户说“我想调用当前的 #2 版本,并且我希望我使用的实现保持不变——即使该 MyProject 项目稍后更新”

请注意我如何在不影响任何现有客户的情况下执行额外的开发:

namespace MyProject {
    namespace Version1 {
        void BoringStableFunction() {...}
    }
    inline namespace Version2 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(int x) {...}
    }
    namespace Version3 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(std::string x) {...}
    }   
}

当我准备好向公众发布我的更改时,只需要进行这个微小的修改:

namespace MyProject {
    namespace Version1 {
        void BoringStableFunction() {...}
    }
    namespace Version2 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(int x) {...}
    }
    inline namespace Version3 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(std::string x) {...}
    }   
}

大多数客户一直在呼叫 MyProject::BoringStableFunction()。他们的代码不需要编辑;它在语法上仍然有效。但他们现在会突然利用我可能在 BoringStableFunction() 内更改的任何新实现。

如果他们大胆使用我的 MyProject::LatestAndGreatest(11),他们将需要被告知他们现在需要更新他们的使用情况。所以这表明,即使使用内联命名空间,仍然需要在程序员与其客户之间的合同中加入思想。