4

我有模板函数,比如说,

template<class T> 
void mysort(std::vector<T>& vec)
{
    size_t b, m, e,
    ...
    mysort(vec, b, m, e);
}

template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)
{
     size_t x, y, z;
     ...
     mysort (vec, x, y, z);
}

公共接口是一个只接受矢量引用的接口。我想隐藏另一个,实现,这样没有客户端代码可以做

mysort(vec, a, b, c);

创建一个类,把实现函数设为private static,感觉不太对劲,我尝试使用匿名命名空间,

namespace abc 
{
    namespace 
    {
        template<class T>
        void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
    }

    template<class T> 
    void mysort(std::vector<T>& vec)...

}

它有帮助,但不完全是淘汰赛......

#include "mysort.h"

int main()
{
    ...
    abc::mysort(vec, a, b, c); // this won't compile, good
}

但是,如果我将其更改为:

#include "mysort.h"

using namespace abc;

int main()
{
    ...
    mysort(vec, a, b, c); // it compiles and runs!!
}

我在 x86_64 上使用 gcc Ubuntu 4.4.3-4ubuntu5。谁能解释为什么它使用 using 指令编译,而不是使用限定名称,以及是否有更好的方法来实现我想要的?

4

2 回答 2

6

常见的用法是创建一个“detail”命名空间,它仅用于内部使用的代码:

namespace abc 
{
    namespace detail
    {
        template<class T>
        void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
    }

    template<class T> 
    void mysort(std::vector<T>& vec)...

}

要回答有关未命名命名空间行为的问题:

未命名的命名空间(它们不称为匿名命名空间)的命名有点奇怪——它们对您来说是未命名的,但编译器实际上会为它生成一个唯一的内部名称。您的示例等效于:

namespace abc 
{
    namespace def // lets say 'def' is unique.
    {
        template<class T>
        void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
    }
    using namespace def;

    template<class T> 
    void mysort(std::vector<T>& vec)...

}

您会注意到它的行为与您未命名的示例相同:您不能在abc::mysort(vec, 1, 2, 3)这里执行,但您可以using namespace abc; mysort(vec, 1, 2, 3).

发生这种情况是因为没有两个abc::mysorts,只有 aabc::def::mysortabc::mysort。当您声明一个实际abc::mysort时,它会隐藏由 引入的那个using namespace def。请注意,如果您注释掉 1-param mysort,您实际上可以说abc::mysort(vec, 1, 2, 3).

因为它是隐藏的,所以合格的调用abc::mysort必须显式查看abc::mysort,并且只能找到 1-param 版本。

但是,通过不合格的调用 via using namespace abc; mysort(vec, 1, 2, 3),它可以使用 ADL 来查找任何匹配的可用函数。

于 2012-12-27T19:52:42.860 回答
0

实际上,我在更高版本的 gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 和 -std=c++0x 中做了一些测试,它完全符合我的预期。

在主文件中,using 指令或 using 限定名称都不允许您调用匿名命名空间内的函数,而匿名命名空间本身位于另一个命名空间内。

我认为原因是编译器确认了最新标准,即默认情况下未命名的命名空间具有内部链接。

在我看来,未命名的命名空间方法应该优于旧的“详细”命名空间实践。

于 2013-01-13T16:18:17.443 回答