Конфликт имен, безымянное пространство имен, шаблон класса

У меня есть шаблон класса Foo<T>, исходя из FooBase,

foo.h:

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

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

Затем у меня есть две единицы перевода, инстанцирующие Foo с разными T«S. Класс, используемый в качестве параметра шаблона, называется 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();

Test2.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 64bit) действительно смущен этим
  2. У меня есть странные ошибки в моем случае из реальной жизни, которые я не могу отследить

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>

И даже намного, намного хуже, при проверке foo.t на test1 находит участника foo.t.x который должен существовать только в test2!

Смотрите скриншоты ниже в QtCreator:

введите описание изображения здесь

введите описание изображения здесь

Все вышеуказанные проблемы решаются, если я назову параметр шаблона T1 в Test1.cpp и T2 в Test2.cpp.

Несмотря на путаницу в GDB, во всех вариантах, которые я пробовал на этом минимальном примере, программа всегда работает правильно (GCC 4.8.2). Например, печать sizeof (T) через виртуальный метод, вызываемый из базы, корректно возвращает 1 а также 4 для test1 и test2 соответственно (пока он печатает 1 а также 1 если я удаляю безымянное пространство имен из-за фактического конфликта имен, который, как я знаю, делает код недопустимым (C ++).

Случай из жизни

В моем случае из реальной жизни у меня есть ошибка, которая:

  1. всегда происходит с «тем же именем в глобальной области видимости» (очевидно)
  2. происходит непредсказуемо с «тем же именем в безымянном пространстве имен»
  3. никогда не встречалось с назначенными вручную уникальными именами

Я не знаю, связано ли это с тем, что назначение уникальных имен вручную решает проблему (не так ли, поскольку они уже были в безымянном пространстве имен ??), или если мой код все еще не работает где-то еще, и мне просто «повезло» (т.е. скрытое неопределенное поведение, которое очень страшно). Я потратил два дня, пытаясь свести к минимуму пример, который все еще дает сбой, но не удался. Мне удалось получить только минимальные примеры работы или мой реальный код, который иногда дает сбой.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]