1

我得到了一些在 MSVC 上编译良好的代码,我正试图让它在 Xcode 中的 Clang 上编译。我目前遇到使用以下 typedef 重新定义类的问题:

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;

    };

}    
4

1 回答 1

2

是的,这是不正确的。永远不应该编译,如果它在 MSVC 上编译 - 可能是编译器的错误。前向声明告诉编译器,这TheNS::Entity将是类,而不是其他(不是枚举、联合或 typedef)。真的,你的代码是一样的

class Entity;   
typedef int Entity;

当然是不正确的。

n3337 9.1/2

仅由类键标识符组成的声明;要么是当前范围内名称的重新声明,要么是标识符作为类名的前向声明。它将类名引入当前范围。

所以,在这之后

class Entity;

编译知道,这Entity将用作类名。该名称可以重新声明为函数(在同一范围内),在这种情况下class Entity,当您想使用Entityclass 时,您应该使用 , (或Entity通过 typedef 重新声明名称,如注释中所述)。

7.1.3/6

在给定的范围内,不应使用 typedef 说明符来重新定义在该范围内声明的任何类型的名称以引用不同的类型。[ 例子:

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

—结束示例]

于 2012-10-02T10:10:16.390 回答