c ++命名空间头痛 [英] c++ Namespace headaches

查看:115
本文介绍了c ++命名空间头痛的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,这个问题已经演变了一点,我想尝试开始(结束)我拍摄的基本目标:

Okay, this question has evolved a bit, and I want to try to start (over) with the basic goals I'm shooting for:


  • 创建用于封装C ++资源获取的旧C语言实体的库代码是初始化的,并且提供基本或更好的异常保证。

  • 启用此代码的客户端,非常自然的C ++时尚,为现有代码创造了大量的开销,将其转换为使用C ++包装器对象(即自动转换为适当的遗留类型,构造函数使用旧类型等)。

  • 限制库代码的命名空间影响。理想情况下,库将有几个子命名空间,提供相关的功能,限制使用命名空间X类型声明的体积和影响 - 就像boost库一样(即使用细节命名空间只注入那些用户合理想要的符号使用和隐藏那些是实现细节;也限制了现有符号可能的新含义的范围,以避免在用户代码中出现意外的隐式转换)

  • 要求客户端明确要求他们真正想要注入到他们的代码库的库的那些部分。这同时限制了包含图书馆标题的影响。客户端代码应该具有合理的控制级别,以便在编译代码时自动将库的哪些部分用于名称解析。

  • 我自己的库代码不应该被重构的脆弱代码结构。如果库的头部不必不断地声明私有typedef以便访问库的该部分的其余部分,那将是理想的。或者换句话说:我希望我的图书馆能够像我的客户在使用所述图书馆时直观地书写。

  • Create library code that wrappers legacy C-language entities in C++ resource acquisition is initialization and also provides basic or better exception guarantee.
  • Enable clients of this code to use it in a very natural C++ fashion w/o creating a lot of overhead to existing code to convert it to use the C++ wrapper objects (i.e. automatic conversion to appropriate legacy types, constructors that take legacy types, etc.)
  • Limit the namespace impact of the library code. Ideally, The library would have several sub-namespaces that provide related functionality that limit the volume and impact of using namespace X type declarations - much as the boost libraries do (i.e. use of details namespaces to only inject those symbols that the user would reasonably want to use, and hide those that are implementation details; also limit the extent of possible new meanings to existing symbols, to avoid surprising implicit conversions within user-code)
  • Require that clients explicitly ask for those parts of the library that they actually want to inject into their code base. This goes hand in hand with limiting the impact of inclusion of the the library's headers. The client code should have a reasonable level of control over which parts of the library are going to be automatically used for name-resolution when they compile their code.
  • My own library code should not have to be riddled with refactor-brittle code constructs. It would be ideal if the library's headers didn't have to constantly declare private typedefs in order to have access to the rest of that section of the library. Or in other words: I want my library to be able to be written as intuitively as my clients get to when making use of said library. Name resolution should include the namespace that the library is defined within in addition to any others that have been explicitly "using'd".

名称解析应包含库中定义的命名空间,以及已明确使用的任何其他命名空间。我经常遇到这种情况,并寻找一个更好的方法...

I come across this scenario often, and am looking for a better way...

我有一个类,C在命名空间N. C有一个成员,Free。它免费是C管理的东西,允许C管理一个新东西。

I have a class, C in namespace N. C has a member, Free. It free's something that C manages, and allows C to manage a new thing.

有几个全局自由函数。在与C相同的命名空间N中还有一些辅助函数,其中之一是一个辅助函数,free是由C管理的,命名为free。

There are several global Free functions. There are also a few helper functions in the same namespace N as C, one of which is a helper that free's the thing managed by C, named free.

例如:

namespace N {

void free(THING * thing);

class C
{
public:
  ... details omitted...
  free()
  { 
    free(m_thing); // <- how best to refer to N::free(THING&)
  }
}

} // namespace N

我可以使用N :: free(m_thing)。但这似乎不幸的是我。有没有办法来引用那些在类范围之外,但是没有解析绝对命名空间(相对一步出来的范围)?

I could use N::free(m_thing). But that seems unfortunate to me. Is there no way to refer to that which is outside the class scope but without resolving absolute namespace (a relative one step out scope-wise)?

在我看来,必须命名N :: free是讨厌的,因为如果这是一个独立的函数,你不会有。如果类的方法名称不同(例如,dispose),也不需要。但是因为我使用了相同的名字,我不能访问它,而不必指定什么是绝对路径 - 而不是相对路径 - 如果你沉溺于我的比喻。

It seems to me that having to name N::free is obnoxious, since you wouldn't have to if this were a free-standing function. Nor would you need to if the class's method name happened to be different (e.g. dispose). But because I've used the same name, I cannot access it without having to specify what amounts to an absolute path - rather than a relative path - if you'll indulge me the analogy.

我讨厌绝对路径。他们使命名空间中的东西变得非常脆弱,因此代码重构变得非常丑陋。另外,如何在函数体中命名东西的规则变得更加复杂,与当前的规则集(我理解他们) - 不规则 - 诱使一个期望和作为一个程序员之间的分裂。

I hate absolute paths. They make moving things around in namespaces very brittle, so code-refactoring becomes much uglier. Plus, the rules of how to name things in function bodies becomes more complex with the current set of rules (as I understand them) - less regular - inducing a schism between what one expects and what one gets as a programmer.

有没有更好的方法来访问与类相同的命名空间中的独立函数,而不必绝对地命名自由函数?

编辑:
也许我应该用一个抽象的例子:

Perhaps I should have gone with a less abstract example:

namespace Toolbox {
  namespace Windows {

// deallocates the given PIDL
void Free(ITEMIDLIST ** ppidl);

class Pidl
{
public:
    // create empty
    Pidl() : m_pidl(NULL) { }

    // create a copy of a given PIDL
    explicit Pidl(const ITEMIDLIST * pidl);

    // create a PIDL from an IShellFolder
    explicit Pidl(IShellFolder * folder);

    ...

    // dispose of the underlying ITEMIDLIST* so we can be free to manage another...
    void Free();
};

所以ITEMIDLIST *来自多个地方,并且被CoTaskMemFree我可以引入Pidl作为一个全局名称,以及作为我的工具箱库一部分的Windows Shell.h头文件中的所有帮助函数。

So ITEMIDLIST* come from a variety of places, and are destroyed with CoTaskMemFree(). I could introduce Pidl as a global name - as well as all of the helper functions in the "Windows Shell.h" header that is part of my toolbox library.

,我会按照它们的关系来区分库中的一些工具 - 在这种情况下,上面所有的都涉及到Windows中的COM编程。我选择Toolbox作为我的库的基本命名空间,并且目前认为我会使用Toolbox :: Windows的Windows-Y函数,类等。

Ideally, I would segment some of the tools in my library by what they relate to - in this case the above all relates to COM programming in Windows. I have chose Toolbox as the base namespace for my libraries stuff, and was currently thinking I'd use Toolbox::Windows for very windows-y functions, classes, etc.

但是C ++命名空间和名称解析规则似乎使这非常困难(因此这个问题)。它使得非常不自然的创建这样的我的代码分段 - 因为koenig查找失败(因为ITEMIDLIST不在我的Toolbox :: Windows命名空间),我没有能力移动它!也不应该我。语言应该足够灵活,IMO,允许扩展库,如我的工具箱库扩展其他人的代码,而不必注入我们的扩展到他们的命名空间(在Win32的情况下,现在存在的大多数代码是GLOBAL NS - 这是首先使命名空间的全部点:避免全局NS拥挤/污染/模糊性/编程惊喜)。

But the C++ namespace and name-resolution rules seem to make this very difficult (hence this question). It makes it very unnatural to create such segmentation of my code - since koenig lookup fails (since ITEMIDLIST is not in my Toolbox::Windows namespace), and I don't have the ability to move it there! Nor should I. The language should be flexible enough, IMO, to both allow for extension libraries such as my Toolbox library to extend other folks code without having to inject my extensions into their namespace (which, in the case of Win32 and the general vast majority of code that exists today, is the GLOBAL NS - which is the whole point of making namespaces in the first place: to avoid global NS crowding / pollution / ambiguity / programming surprises).

所以,我回来了,有一个更好的方法做到这一点:扩展现有的代码库,而不污染他们的NS与我的扩展,但仍然允许直观和有用的名称解析,如果我的代码在他们的NS,但我的代码的客户端明确介绍(即我不想注入我的代码willy-nilly,但只有显式请求)?

另一种想法:也许满足我上述criterea将是如果我有以下:

Another Thought: Perhaps what would satisfy my above criterea would be if I had the following:

using namespace X {
  code here...
}

这样的结构在任何地方,包括在一个标题,我不必担心将X拖入我的客户端的代码,但我会有同样的自由写我的源代码,如果我在根命名空间。 / p>

Where I could place such a construct anywhere, including in a header, and I would not have to be concerned about dragging X into my client's code, but I would have the same freedom to write my source code as I would if I were in the root namespace.

推荐答案

我不认为避免必须限定命名空间范围 $ c>这里,但是应该注意,这和绝对路径不一样。首先,如果你有嵌套的命名空间,你只需要引用最里面的命名空间:

I don't see to avoid having to qualify namespace-scope free() here, but it should be noted that this is not the same as an "absolute path". For one thing, if you have nested namespaces, you only have to refer to the innermost one:

namespace N1 {
  namespace N2 {
    namespace N3 {
      void free(THING * thing);

      class C {
      public:
        free() {
          N3::free(m_Thing); // no need to do N1::N2::
        }
      };
    }
  }
}

以回应已编辑的问题。再次,我没有看到任何方法来做到这一点在你描述的确切情况。但是,它似乎不是惯用的C ++方法 - 更常见的方法是提供自己的包装类, ITEMIDLIST 管理所有的分配,RAII-风格,并暴露原始句柄(例如,通过转换运算符a ATL或显式成员函数如 c_str()如果你想要额外的安全)。这将不再需要您的免费,以及任何其他免费的功能,你可能想要的,因为你控制包装类型和它的命名空间,你可以使用ADL一样。

in response to edited question. Again, I do not see any way to do this in the exact scenario that you describe. However, it doesn't seem to be idiomatic C++ approach - the more common way to do the same is to provide your own wrapper class for ITEMIDLIST that manages all allocations, RAII-style, and exposes the original handle (e.g. via conversion operators a la ATL, or an explicit member function like c_str() if you want extra safety). That would remove the need for your free altogether, and for any other free function that you might want there, since you control the wrapper type and the namespace it's in, you can use ADL as usual.

。这个问题的这一部分:

. This part of the question:


允许直观和有用的名称解析,如果我的代码在他们的NS,但明确介绍我的代码的客户端(即我不想注入我的代码willy-nilly,但只有显式请求)?

这不是你把它放在一个命名空间,并且你的客户端写使用命名空间... ,将实现?

Isn't this precisely what you putting it in a namespace, and your client writing using namespace ..., will achieve?

这篇关于c ++命名空间头痛的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆