9

MSVC10 RC コンパイラを使用して、C++0x、特にラムダ式と decltype を使用してコードの一部を簡素化しようとしています。

次の非常に奇妙な問題に遭遇しました。

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([]() { })

「コンパイラのバグ」と大声で叫ぶのは嫌いですが、このエラーの適切な説明がまったく見つかりません。どうやら、外側のラムダ式の内部では、コンパイラは foo内側のラムダの関数テンプレートを特殊化できません。

ただし、次のように、 の定義がfoo戻り値の型をハードコードするように変更された場合:

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

その後、すべてが正常にコンパイルされます。

私が気付いていない別のラムダのスコープ内でラムダ式パラメータの戻り値の型を推測するために使用される場合、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内部ラムダのタイプに関係しているようです。(?)

于 2010-02-25T20:30:47.430 に答える