如何使命名空间别名仅对类可用

49

我期望能够在类声明中使用命名空间别名,但却收到了编译器语法错误。

struct MyClass
{
    namespace abc = a_big_namespace;
    void fn() {
        abc::test();
    }
};

我唯一能让它工作的方法是在每个函数中添加别名。

void fn() {
    namespace abc = a_big_namespace;
    abc::test();
}

另外,我希望能够使用函数参数的别名,但我还没有找到解决方法。

void fn(abc::testType tt) {
    abc::test(tt);
}

有没有一种方法可以实现我想要的功能?

编辑:我的解决方案

我发现对于我的特定问题,我不需要未命名的命名空间,可以简单地这样做:

namespace myspace
{
    namespace abc = a_big_namespace;

    struct MyClass
    {
       void fn(abc::testType tt) {
          abc::test(tt);
       }
    };
}

要切换到另一个库,也就是我的别名命名空间所指的内容,我只需更改别名即可。这种方法甚至允许我在同一文件中两次使用相同的类,每次都引用不同的库。 感谢您的帮助。

4个回答

48

类定义中的命名空间别名是不合法的,根据语言规范。

它只允许在命名空间作用域函数作用域中出现。

您可以在命名空间作用域创建一个别名。但这将创建一个永久别名,也可以从其他文件中使用。然而,解决方案很简单:您可以使用未命名命名空间来防止别名(以及来自大型命名空间的所有符号)对其他文件可见。以下是实现方法:

//MyFile.cpp
namespace myspace
{ 
    namespace   //this is unnamed namespace
    {
       namespace abc = a_big_namespace;     
    }
    struct MyClass 
    {
      void fn() 
      { 
         abc::test();  //don't worry, this will work!
      } 
    };
}

//OtherFile.cpp

myspace::abc::test(); //error - that means, prevention worked.

别名在其他文件中不可见。当编译OtherFile.cpp时,GCC(4.5.0)会报错:

'myspace::abc' 未声明

这证明了别名abc只能在MyFile.cpp中可见,多亏了匿名命名空间。

演示:http://www.ideone.com/2zyNI(虽然它不能展示OtherFile的概念,因为我无法在ideone.com上使用多个文件)


1
非常感谢Nawaz,我没有意识到类作用域中的别名是非法的,也不知道有解决方法。我之前遇到过匿名命名空间,所以我会按照你的建议完全实现我的代码。再次感谢。 - Ant
5
这里对所描述的解决方法有一个注意事项:虽然这些别名在不同的cpp文件中是不可见的,但它们在其他头文件中是可见的。例如,在一个头文件中应用此解决方法后,项目中的每个其他头文件都可以使用相同的别名,而不考虑其周围的命名空间。你将无法在项目中的任何其他头文件中将相同的别名分配给另一个命名空间,并且你只能在单个头文件中定义一次给定的别名。这适用于Visual Studio 2013,其他平台可能不同。 - Hoobajoob
可以在命名空间范围内创建别名。但这将创建一个永久别名,可以从其他文件中使用。你能提供一下关于命名空间别名跨编译单元可见的参考资料吗? - Eric
10
我不确定这对于解决问题有什么帮助。在cpp文件中,命名空间别名也无法在其他任何地方看到。据我所知,匿名命名空间是为了避免具有静态链接的函数或数据出现导出/冲突符号。 - Catskul
如果MyClass需要在头文件中定义,有解决方案吗? - Tagli
显示剩余2条评论

3
命名空间别名的作用域是代码块。因此,你可以将其放在任何代码块中。
但是,你不能将其放在类内部,因为这将意味着它是类的成员。命名空间别名不能成为成员。
关于命名空间别名的更多信息:
C++中命名空间别名的作用域是什么?
命名空间

1
抱歉,您的答案不令人满意。类和命名空间非常相似,但我们可以有内部类。我们甚至可以有内部typedefs,并为基本方法使用内部usings。甚至包括内部静态断言!因此,在我的看法中,没有内部命名空间听起来完全是委员会做出的武断判断。 - v.oddou

-2

当然,你也可以将别名放在类的外面:

namespace abc = a_big_namespace;     

struct MyClass {
    void fn()
    { abc::test(); } 
}; 

2
我的要求是将命名空间限制在类中,因为我使用相同的别名来引用两个不同的库,具体取决于我正在使用哪个类。所以是的,它可以工作,但它不符合我的要求。不过还是谢谢你的建议。 - Ant

-2

如果你在结构体外部声明别名,它就能正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接