9

我正在尝试使用 C++0x,特别是 lambda 表达式和 decltype 来简化我的一些代码,使用 MSVC10 RC 编译器。

我遇到了以下非常奇怪的问题:

template <typename F>
auto foo(F f) -> decltype(f()){
  return f();
}

template <typename F>
void bar(F f){
  f();
}

int main() {
  bar([](){
    foo([]() { }); // error C2893: Failed to specialize function template ''unknown-type' foo(F)'
  });
}

如注释中所示,编译器在该行生成错误foo([]() { })

我讨厌大喊“编译器错误”,但我真的看不出这个错误有什么好的解释。显然,在外部 lambda 表达式内部时,编译器无法 foo为内部 lambda 专门化函数模板。

但是,如果将 的定义foo更改为硬编码返回类型,如下所示:

template <typename F>
void foo(F f){
  return f();
}

然后一切都编译得很好。

当用于在我不知道的另一个 lambda 范围内推断 lambda 表达式参数的返回类型时,是否存在一些模糊的 decltype 怪癖?

4

2 回答 2

3

这些只是供人们观察的一些测试用例。

作品

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

void dummy() {}

int main()
{
    auto x = []()
            {   // non-lambda parameter
                foo(dummy);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto f = [](){};
    auto x = [&]()
            {    // pre-defined lambda
                foo(f);
            };
}

失败

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda
                foo([]{});
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda
                auto f = []{};
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda, explicit return
                // (explicit return type fails too, `-> void`)
                auto f = [](){ return; };
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda, explicit return non-void
                // (explicit return type fails too, `-> int`)
                foo([]{ return 5; }); 
            };
}

所以它似乎与范围void内部 lambda 的类型有关,即使是明确的。(?)

于 2010-02-25T20:30:47.430 回答
0

'auto' 的本质是允许编译器计算类型。但是您的第一个示例包含彼此的递归引用,因此要计算 foo 的 auto,您需要 bar 并创建 bar 的实例,您需要 foo。

另一方面,第二个例子明确地告诉编译器:“它应该是一个指向函数的指针,所以冷静一下”。由于指向函数的指针是经过良好计算的,因此类型编译器知道将保留什么。仅作类比:比较成员的前向声明

struct A; //forward
...
A a1; //this is an error
A *a2; //this is correct since pointer calculated in bytes
于 2010-02-25T16:43:53.823 回答