MSVC10中出现了奇怪的编译器错误

4

我有以下代码:

std::for_each(tokens.begin(), tokens.end(), [&](Token& t) {
    static const std::unordered_map<std::wstring, Wide::Lexer::TokenType> mapping([]() -> std::unordered_map<std::wstring, Wide::Lexer::TokenType>
    {
        // Maps strings to TokenType enumerated values
        std::unordered_map<std::wstring, Wide::Lexer::TokenType> result;

        // RESERVED WORD
        result[L"namespace"] = Wide::Lexer::TokenType::Namespace;
        result[L"for"] = Wide::Lexer::TokenType::For;
        result[L"while"] = Wide::Lexer::TokenType::While;
        result[L"do"] = Wide::Lexer::TokenType::Do;
        result[L"type"] = Wide::Lexer::TokenType::Type;

        // PUNCTUATION
        result[L"{"] = Wide::Lexer::TokenType::OpenCurlyBracket;
        result[L"}"] = Wide::Lexer::TokenType::CloseCurlyBacket;
        return result;
    }());
    if (mapping.find(t.Codepoints) != mapping.end()) {
        t.type = mapping.find(t.Codepoints)->second;
        return;
    }
    t.type = Wide::Lexer::TokenType::Identifier; // line 121
});

这个步骤会遍历一系列的tokens,根据编码点的内容,将其与相关枚举值进行对比并赋予对应值。如果未找到,则将其赋值为"Identifier"。但是,此处存在编译错误。

1>Lexer.cpp(121): error C2065: '__this' : undeclared identifier
1>Lexer.cpp(121): error C2227: left of '->Identifier' must point to class/struct/union/generic type

这是完整的错误信息,没有警告,也没有其他的错误。怎么办?我该如何修复这个错误?

编辑:我进行了一些重构,并且在一个更简单的lambda中遇到了完全相同的问题。

auto end_current_token = [&] {
    if (current != Wide::Lexer::Token()) {

        current.type = Wide::Lexer::TokenType::Identifier; // error line

        if (reserved_words.find(current.Codepoints) != reserved_words.end())
            current.type = reserved_words.find(current.Codepoints)->second;
        if (punctuation.find(current.Codepoints[0]) != punctuation.end())
            current.type = punctuation.find(current.Codepoints[0])->second;

        tokens.push_back(current);
        current = Wide::Lexer::Token();
    }
};

我已清理并重建了该项目。
我修复了这个问题。
auto end_current_token = [&] {
    if (current != Wide::Lexer::Token()) {

        // WORKAROUND compiler bug- dead code
        struct bug_workaround_type {
            int Identifier;
        };
        bug_workaround_type bug;
        bug_workaround_type* __this = &bug;

        current.type = Wide::Lexer::TokenType::Identifier;

        if (reserved_words.find(current.Codepoints) != reserved_words.end())
            current.type = reserved_words.find(current.Codepoints)->second;
        if (punctuation.find(current.Codepoints[0]) != punctuation.end())
            current.type = punctuation.find(current.Codepoints[0])->second;

        tokens.push_back(current);
        current = Wide::Lexer::Token();
    }
};

不,真的。现在它已经编译并且运行得非常好了。

这个函数属于哪个类?Wide::Lexer::TokenType::Identifier 是什么意思? - Nicol Bolas
@K-ballo:我不知道,但是在lambda中没有对this的引用,所以我认为它并不重要。 - Puppy
这可能是预处理器冲突吗?如果是的话,在预处理后,您需要查看第121行。 - sehe
@GMan:不,所有类型引用都是完全限定的。 - Puppy
1
@sehe:这个项目不是最大的,但也不小到我需要逐个重建它。至于类型,编译器似乎并不在意——我将其更改为永远不会过时的成员函数指针,所以我怀疑它不会很快用到它。 - Puppy
显示剩余9条评论
2个回答

1

顺便说一句,我尝试着构建一个最小的工作示例,以便在VS2010上编译,并且以下内容已经成功编译,没有出现错误。

#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>

namespace Wide { namespace Lexer {
    enum TokenType
    {
        OpenCurlyBracket,
        CloseCurlyBacket,
        Namespace,
        For,
        While,
        Do,
        Type,
        Identifier,
    };
} }

struct Token
{
    std::wstring Codepoints;
    Wide::Lexer::TokenType type;
};

int main()
{
    std::vector<Token> tokens;
    std::for_each(tokens.begin(), tokens.end(), [&](Token& t) {
        static const std::unordered_map<std::wstring, Wide::Lexer::TokenType> mapping([]() -> std::unordered_map<std::wstring, Wide::Lexer::TokenType>
        {
            // Maps strings to TokenType enumerated values
            std::unordered_map<std::wstring, Wide::Lexer::TokenType> result;

            // RESERVED WORD
            result[L"namespace"] = Wide::Lexer::TokenType::Namespace;
            result[L"for"] = Wide::Lexer::TokenType::For;
            result[L"while"] = Wide::Lexer::TokenType::While;
            result[L"do"] = Wide::Lexer::TokenType::Do;
            result[L"type"] = Wide::Lexer::TokenType::Type;

            // PUNCTUATION
            result[L"{"] = Wide::Lexer::TokenType::OpenCurlyBracket;
            result[L"}"] = Wide::Lexer::TokenType::CloseCurlyBacket;
            return result;
        }());
        if (mapping.find(t.Codepoints) != mapping.end()) {
            t.type = mapping.find(t.Codepoints)->second;
            return;
        }
        t.type = Wide::Lexer::TokenType::Identifier; // line 121
    });
}

你能够对这段代码进行二分查找,找出最小的编辑问题并展示出来吗?


我认为将这个问题归类为“编译器错误”是相当安全的。 - Puppy

1

我现在也遇到了同样的问题。我使用了其他类型,但对于你的情况,应该是这样的:

auto end_current_token = [&] {

    using Wide::Lexer::TokenType;           // <-- this line solves problem

    if (current != Wide::Lexer::Token()) {
        current.type = Wide::Lexer::TokenType::Identifier;

现在它编译得很好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接