12

我遇到了一个奇怪的问题。以下简化代码重现了 MSVC 2010 中的问题:

template <typename T>
struct dummy
{
    static T foo(void) { return T(); }
};

int main(void)
{
    typedef dummy<bool> dummy_type;
    auto x = []{ bool b = dummy_type::foo(); };
    // auto x = []{ bool b = dummy<bool>::foo(); }; // works
}

我在函数中本地创建的typedef在 lambda 中似乎不可见。如果我用typedef实际类型替换它,它会按预期工作。

以下是其他一些测试用例:

// crashes the compiler, credit to Tarydon
int main(void)
{
    struct dummy {};

    auto x = []{ dummy d; };
}

// works as expected
int main(void)
{
    typedef int integer;

    auto x = []{ integer i = 0; };
}

我现在没有可用的 g++ 来测试它。这是 C++0x 中的一些奇怪规则,还是只是编译器中的错误?

从上面的结果来看,我倾向于错误。虽然崩溃绝对是一个错误。


目前,我已经提交了两个错误报告

上面的所有代码片段都应该编译。该错误与在本地定义的范围上使用范围解析有关。(由dvide发现。)

崩溃错误与...谁知道呢。:)


更新

根据错误报告,它们都已在 Visual Studio 2010 的下一个版本中得到修复。(虽然这似乎不是这种情况;也许是 VS11。)

4

4 回答 4

9

从 n3000, 5.1.2/6,

lambda 表达式的复合语句产生函数调用运算符的函数体 (8.4),但出于名称查找 (3.4) 的目的,……复合语句在 lambda 表达式的上下文中被考虑。

毫不奇怪,本地类型应该是可见的。

于 2010-01-23T06:40:16.360 回答
3

lambda 也无法检测到函数局部枚举。

int main()
{   
    enum E {A, B, C};   
    auto x = [](){ int a = A; }; 
    //auto y = [](){ E a = A; }; // this will crash the compiler
}

错误 C3493:无法隐式捕获“A”,因为未指定默认捕获模式

以下是一个解决方法,但可能有问题。

int main()
{   
    enum E {A, B, C};   
    auto x = [=](){ int a = A; };
    // typedef E F; 
    // auto y = [=](){ F a = A; }; // this compiles ok
}
于 2010-05-21T18:01:53.513 回答
2

这并不是您问题的真正答案,而只是进一步探索问题。我想知道编译器是否在处理封闭范围内声明的类型时遇到问题,所以试了一下:

#include <iostream>

template <typename Func>
void do_test(Func pFunc) {
}

template <typename T>
void test_trait(void) {
   class Something { public: int foo; };

   do_test ([] (T pX) {
      Something A; A.foo = 12;
   });
}

int main(void) {
    test_trait<int> ();
}

在这里,我只是想在封闭范围内创建一个本地类型,并在 lambda 函数中使用它。这不仅不能编译(使用 Visual Studio 2010,Beta 2),而且实际上会使编译器因 C1001 内部错误而崩溃。

于 2010-01-23T06:05:44.170 回答
2

我已经提交了两个错误报告。

我们会看看情况如何。:)


更新

这两个错误都已被标记为已修复:

感谢您的反馈。我们之前已经发现了这个错误,我们已经在下一个版本中修复了它。感谢您使用该产品。

谢谢,
Ulzii Luvsanbat
Windows C++ 团队

所以我们开始了。

于 2010-01-23T06:52:12.843 回答