名称冲突,未命名的命名空间,类模板

时间:2016-03-06 12:13:17

标签: c++ templates namespaces unnamed-namespace

我有一个类模板Foo<T>,派生自FooBase

foo.h中:

class FooBase
{
public:
    virtual ~FooBase() {}
};

template <class T>
class Foo : public FooBase
{
public:
    T t;
};

然后,我有两个翻译单元用不同的T来实例化Foo。用作模板参数的类在两个转换单元中都称为T,但受未命名的命名空间保护。每个翻译单元都定义了一个自由函数。

Test1.h:

void test1();

Test1.cpp:

#include "Test1.h"
#include "Foo.h"
#include <cassert>

namespace { class T {}; }

void test1()
{
    Foo<T> foo;
    FooBase & base = foo;
    assert(&base == &foo); // To be able to breakpoint here
}

Test2.h:

void test2();

测试2.cpp:

#include "Test2.h"
#include "Foo.h"
#include <cassert>

namespace { class T { int x; }; }

void test2()
{
    Foo<T> foo;
    FooBase & base = foo;
    assert(&base == &foo); // To be able to breakpoint here
}

最后,我有一个调用自由函数的main,并且我链接了所有三个翻译单元。

main.cpp中:

#include "Test1.h"
#include "Test2.h"

int main()
{
    test1();
    test2();
}

问题:这是合法的C ++ 11吗?

我认为应该是因为名称冲突由未命名的命名空间解决。但是,我现在有疑问,因为:

  1. GDB(v7.7.1,关于Kubuntu 14.04 64位)真的很困惑这个
  2. 我的现实案例中有一些奇怪的错误,我无法追踪
  3. GDB

    GDB在test2()上发出这些警告:

    can't find linker symbol for virtual table for `FooBase' value
    can't find linker symbol for virtual table for `Foo<(anonymous namespace)::T>' value
    

    并且无法确定base实际上是动态类型Foo,因此检查其成员t。而且,而不是好的

    <vtable for Foo<(anonymous namespace)::T>+16>
    

    我得到test1,我在test2上得到以下内容:

    <_ZTV3FooIN12_GLOBAL__N_11TEE+16>
    

    甚至更糟糕的是,在test1上检查foo.t时,它会找到应该只存在于test2中的成员foo.t.x

    请参阅下面的QtCreator中的屏幕截图:

    enter image description here

    enter image description here

    如果我在Test1.cpp中命名模板参数T1并在Test2.cpp中命名T2,则会解决以上所有问题。

    尽管存在GDB混淆,但在我尝试围绕这个最小示例的所有变体上,程序似乎总是表现正常(GCC 4.8.2)。例如,通过从base调用的虚拟方法打印sizeof(T)正确地分别返回14 for test1和test2(如果我删除它会打印11未命名的命名空间,由于实际的名称冲突,我知道这使得代码不合法​​C ++)。

    现实案例

    在我的真实案例中,我有一个段错误:

    1. 始终以&#34;全局范围内的相同名称出现&#34; (显然)
    2. 在未命名的命名空间&#34;
    3. 下以&#34;相同的名称无法预测地发生
    4. 从未发生过手动分配的唯一名称
    5. 我不知道是不是因为分配唯一名称会手动修复问题(可能是因为它们已经在未命名的命名空间中了),或者我的代码在其他地方仍然被破坏了我和我#39;我只是&#34;幸运&#34; (即隐藏的未定义行为,这是非常可怕的)。我花了两天的时间试图减少一个仍然以这种方式崩溃的最小例子,但失败了。我只设法得到最小的工作示例,或者我的实际代码有时会崩溃。

0 个答案:

没有答案