【问题标题】:Nested namespaces and ambiguous symbol嵌套命名空间和模棱两可的符号
【发布时间】:2013-08-10 08:10:01
【问题描述】:

我遇到了一个涉及嵌套命名空间和模板类的问题。我还能够创建与实际代码产生相同错误的测试用例,但更具可读性。

使用 VS2012 和 2010 平台工具集编译以下代码会导致错误:

namespace A
{
   namespace B
   {
      namespace C1
      {
         struct SMeasResult{};
      }
      namespace C2
      {
         struct SMeasResult{};
      }
   }
}

namespace C1Test
{
   using namespace A::B::C1;

   template<typename T>
   class Fook
   {
   public:

      void Yu()
      {
         SMeasResult Field;
      }
   };
}

namespace C2Test
{
   using namespace A::B::C2;

   template<typename T>
   class Fook
   {
   public:

      void Yu()
      {
         SMeasResult Field;
      }
   };
}

void m(){
   C1Test::Fook<int> yu;
   C2Test::Fook<int> me;

   yu.Yu();
   me.Yu();
}

具体报错如下:

1>------ Build started: Project: MultiVicomTest (Visual Studio 2010), Configuration: Debug Win32 ------
1>  test.cpp
1>c:\code\test.cpp(27): warning C4101: 'Field' : unreferenced local variable
1>          c:\code\test.cpp(26) : while compiling class template member function 'void C1Test::Fook<T>::Yu(void)'
1>          with
1>          [
1>              T=int
1>          ]
1>          c:\code\test.cpp(49) : see reference to class template instantiation 'C1Test::Fook<T>' being compiled
1>          with
1>          [
1>              T=int
1>          ]
1>c:\code\test.cpp(43): error C2872: 'SMeasResult' : ambiguous symbol
1>          could be 'c:\code\test.cpp(11) : A::B::C2::SMeasResult'
1>          or       'c:\code\test.cpp(7) : A::B::C1::SMeasResult'
1>          c:\code\test.cpp(42) : while compiling class template member function 'void C2Test::Fook<T>::Yu(void)'
1>          with
1>          [
1>              T=int
1>          ]
1>          c:\code\test.cpp(50) : see reference to class template instantiation 'C2Test::Fook<T>' being compiled
1>          with
1>          [
1>              T=int
1>          ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我不明白为什么符号 'SMeasResult' 对编译器来说会模棱两可,因为它是在单独的命名空间中使用的。 到目前为止我能发现的是,这个问题只在类是模板类时出现。移除模板定义时不会出现同样的问题。

如果我做错了什么,谁能告诉我?

【问题讨论】:

  • 我很确定这是一个错误。 Gcc 和 clang 编译得很好,我也不明白为什么它会模棱两可。
  • 自 C++98 以来,MSVC 从未按照语言标准的要求对模板中使用的名称实施两阶段查找。这个错误很可能是其结果。

标签: c++ visual-studio-2010 templates namespaces using


【解决方案1】:

这对我来说实际上看起来像是一个编译器错误。当您考虑到函数的 C1Test 版本编译时没有歧义时,我怀疑 namespace C1Test 中的 using 命名空间会以某种方式持续到 C2Test 命名空间中。

g++ 4.4 和 4.5 都可以很好地编译这段代码这一事实进一步证实了这一点。

【讨论】:

  • 是的,使用是在视觉上泄露的,而不是在 g++ 中。由于我不是这个关键字的忠实粉丝,我不知道标准对此有何评论。
  • 有趣的是,在 C1Test 之前使用命名空间 C2Test 重新排序代码会导致在 C2Test 内报告 SMeasResult 的“歧义”仍然C1 中的声明出现在 C2 之前这一事实似乎比使用顺序更重要。
  • 我的错误——重要的是模板实例化的顺序,而不是任何声明。无论C1C2C1TestC2Test 的声明顺序如何,要实例化的第二个模板都会因错误而被“指责”。
  • 感谢您在 g++ 上进行测试。起初我担心这种情况在标准中没有完全指定,但看起来,VS 编译器是罪魁祸首。不幸的是,由于遗留代码和对其他库的依赖,我们无法使用其他编译器。我想我们将不得不通过完全指定这些模板定义中的符号来解决这个问题,直到编译器团队能够解决这个问题。
【解决方案2】:

尝试使用 使用 A::B::C1::SMeasResult; 和 使用 A::B::C2::SMeasResult; 在您的 C1Test 和 C2Test 命名空间中。这样就解决了问题。

顺便说一句 为什么需要这么多命名空间? STL 很大,但它只使用 1 个命名空间 - std。

【讨论】:

  • Boost 也很大,它使用了很多命名空间;)
  • 在这种特定情况下,我们有一个庞大的代码库,其中包含与不同种类的无线电技术相关的代码。我们希望将相应的类移动到类似于它们所代表的技术的命名空间中,因此需要许多命名空间。由于还集成了许多其他平台(.NET、Java),我们选择了与它们类似的方式(想想这些平台中大量的命名空间)。
猜你喜欢
  • 1970-01-01
  • 2015-01-30
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 2013-09-16
  • 1970-01-01
  • 2012-03-17
相关资源
最近更新 更多