ラムダ内から呼び出された場合、Decltypeを使用してリターンタイプを推定する機能テンプレートをインスタンス化することができませんか?

StackOverflow https://stackoverflow.com/questions/2335530

質問

MSVC10 RCコンパイラを使用して、C ++ 0x、特にLambda式と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();
}

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

私が知らない別のラムダの範囲内に、ラムダ発現パラメーターのリターンタイプを推定するために使用される場合、dedtypeのあいまいな癖がありますか?

役に立ちましたか?

解決

これらは、人々が観察するためのいくつかのテストケースです。

作品

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 明示的にされたとしても、内部ラムダのタイプ。(?)

他のヒント

「自動」の性質は、コンパイラがタイプを計算できるようにすることです。ただし、最初の例には互いに再帰的な参照が含まれているため、fooの自動を計算するには、バーが必要であり、fooが必要なバーのインスタンスを作成するには、fooが必要です。

一方、2番目の例では、コンパイラに「機能へのポインターである必要があるため、しばらく落ち着かせる必要がある」と明示的に伝えています。 Pointer to Functionは十分に計算されるため、タイプコンパイラは正確に予約されるものを知っています。アナログのためだけに:メンバーのフォワード宣言を比較します

struct A; //forward
...
A a1; //this is an error
A *a2; //this is correct since pointer calculated in bytes
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top