VS2008(+?) 模板化函数和“使用命名空间”的编译器错误

问题描述 投票:0回答:2

我发现某些代码(如下)的这种奇怪情况无法在 Visual Studio 2008 下编译,并在第 12 行产生“错误 C2872:'Ambiguity':不明确的符号”。

删除最后一行上的 using

namespace RequiredNamespace
可以修复错误,但我希望将
using namespace
放在文件末尾应该没有任何效果。它还依赖于
AnotherFunction
作为模板函数,因此我希望编译器在错误的范围内生成模板化函数,或者在执行此操作之前不会重置正在使用的命名空间列表。

相同的代码在 GCC 下编译。

两个编译器似乎都在

TemplatedFunction
定义之后生成
using namespace Namespace
的代码,至少据我通过引入错误并查看它们的输出顺序可以看出。

namespace Ambiguity
{
    class cSomeClass
    {
    };

    template<class T>
    void TemplatedFunction(T a)
    {
        // this is where the error occurs, the compiler thinks Ambiguity
        // might refer to the class in RequiredNamespace below
        Ambiguity::cSomeClass(); 
    }
}

namespace RequiredNamespace 
{
    // without a namespace around this class, the Ambiguity class 
    // and namespace collide
    class Ambiguity
    {
    };
}

int main()
{
    // to force the templated function to be generated
    Ambiguity::TemplatedFunction(4); 
}

// removing this removes the error, but it shouldn't really do anything
using namespace RequiredNamespace; 

显然这是一个制造的示例,但原件是从真实案例中提取的,其中

using namespace
位于由第 3 方代码生成的自动生成文件中。

这是编译器中的错误吗?

c++ templates namespaces
2个回答
5
投票

我同意这是一个错误,但是可以通过生成与您的文件相对应的程序集列表(使用 cl.exe 的 /Fa 选项)来了解正在发生的情况。

因此,注释掉 using 声明,生成 .asm 文件并在文本编辑器中打开它。扫描该文件,可以看到模板的实例化位于文件的底部(以

??$TemplatedFunction@H@Ambiguity@@YAXH@Z PROC
开头),并且位于为主函数生成的程序集下方(以
_main   PROC
开头)。错误消息显示“请参阅对函数模板实例化的引用”,因此它指的是模板函数的实例化,并且程序集列表清楚地表明此实例化位于文件的底部。

现在,编辑代码以用

NonTemplatedFunction(int a)
替换模板函数并编译,生成汇编列表。查看汇编列表,您将看到为
NonTemplatedFunction(int a)
生成的汇编代码出现在
_main   PROC
上方。

这些胡言乱语是什么意思?当 Visual Studio 2008 编译器将模板转换为实际代码时,它实际上是在 using 声明之后将一些代码附加到文件末尾。您的 using 声明意味着自动生成的代码中的名称是“不明确的”。 gcc用来实例化模板的过程显然避免了这个问题。


2
投票

我相信这是一个错误,根据 C++03 标准的 7.3.4 第 1 段:

using-directive 指定指定命名空间中的名称可以在 using-directive 出现在 using-directive 之后的范围内使用。

所以你的文件结尾 using 声明应该没有效果。

© www.soinside.com 2019 - 2024. All rights reserved.