& quot; Переопределение Typedef с разными типами & quot; ошибка в Clang при работе кода MSVC

Мне дали код, который прекрасно компилируется на MSVC, и я пытаюсь заставить его скомпилировать на Clang в Xcode. В настоящее время я сталкиваюсь с проблемой, при которой класс переопределяется с помощью следующего определения типа:

typedef std::map<MyNS::istring, EntityState> Entity;

Глядя на предварительно обработанный вывод, я вижу, что есть две предварительные декларации class Entity до этого typedef. Тем не менее, фактическое определение class Entity не находится в предварительно обработанном выводе, но находится в том же пространстве имен, что и новая карта сущностей (не MyNS хоть…). Это предварительные декларации, которые вызывают эту ошибку? И есть ли какой-то способ, которым это может быть допустимо в MSVC и не работает из-за педантизма Clang?

РЕДАКТИРОВАТЬ: У меня нет MSVC под рукой, но вот фрагмент, который я собрал, чтобы продемонстрировать, какую ошибку я получаю (я упростил определения так, чтобы все это помещалось в небольшом пространстве). Это вызывает ту же ошибку, что и я, когда я пытаюсь скомпилировать его с помощью Clang. Будет ли это работать в MSVC?

namespace TheNS {

class Entity;

struct EntityState
{
std::string aString, anotherString;
int anInt;

EntityState() {}

EntityState(std::string a, std::string b, int i)
{
// constructor
}
};

typedef std::map<std::string, EntityState> Entity;

class Entity
{
public:
void SomeFunction();

private:
int m_aVar;

};

}

1

Решение

Да, это не правильно. Никогда не должен компилироваться, если он компилируется в MSVC — возможно, это ошибка компилятора. Предварительное объявление сообщает компилятору, что TheNS::Entity будет классом и ничего более (не enum, union или typedef). На самом деле, ваш код такой же, как

class Entity;
typedef int Entity;

Конечно это неверно.

N3337 9,1 / 2


Объявление, состоящее исключительно из идентификатора ключа класса; это либо переопределение имени
в текущей области или в предварительном объявлении идентификатора в качестве имени класса. Он вводит имя класса
в текущем объеме.

Итак, после этого

class Entity;

компилирует знает, что Entity будет использоваться в качестве имени класса. Это имя может быть объявлено как функция (в той же области видимости), в этом случае вам следует использовать class Entityкогда вы хотите использовать Entity класс (или переопределить Entity имя по typedef, как сказано в комментариях).

7.1.3 / 6


В данном контексте спецификатор typedef не должен использоваться для переопределения имени любого типа, объявленного в этом
область, чтобы обратиться к другому типу. [ Пример:

class complex { /∗ ... ∗/ };
typedef int complex; // error: redifinition

— конец примера]

1

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

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

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