1. ホーム
  2. c++

[解決済み] C++11の再帰的ラムダ関数

2022-02-24 23:31:31

質問

C++11の初心者です。 以下の再帰的ラムダ関数を書いているのですが、コンパイルできません。

sum.cpp

#include <iostream>
#include <functional>

auto term = [](int a)->int {
  return a*a;
};

auto next = [](int a)->int {
  return ++a;
};

auto sum = [term,next,&sum](int a, int b)mutable ->int {
  if(a>b)
    return 0;
  else
    return term(a) + sum(next(a),b);
};

int main(){
  std::cout<<sum(1,10)<<std::endl;
  return 0;
}

コンパイルエラーです。

vimal@linux-718q:~/Study/09C++/c++0x/lambda> g++ -std=c++0x sum.cpp

sum.cpp: ラムダ関数内。 sum.cpp:18:36: エラー: ' ((<lambda(int, int)>*)this)-><lambda(int, int)>::sum ' は関数として使用できません

gccバージョン

gcc version 4.5.0 20091231 (experimental) (GCC)

の宣言を変更すると sum() のようにすると、動作します。

std::function<int(int,int)> sum = [term,next,&sum](int a, int b)->int {
   if(a>b)
     return 0;
   else
     return term(a) + sum(next(a),b);
};

どなたか、この件に光を当てていただけませんか?

解決方法は?

の違いについて考えてみましょう。 オート バージョンと完全に指定されたタイプバージョンとがあります。 その 自動 キーワードは初期化されたものから型を推定しますが、初期化するものはその型が何であるかを知っている必要があります(この場合、ラムダクロージャはそれが捕捉する型を知っている必要があります)。 鶏と卵の問題のようなものだ。

一方、完全に指定された関数オブジェクトの型は、代入されるものについて何も知る必要がない。したがって、ラムダのクロージャは、同様に、捕捉する型について完全に情報を得ることができる。

あなたのコードを少し修正すると、より理解しやすくなるかもしれません。

std::function<int(int,int)> sum;
sum = [term,next,&sum](int a, int b)->int {
if(a>b)
    return 0;
else
    return term(a) + sum(next(a),b);
};

当然ながら、これは 自動 . 再帰的ラムダ関数は完全に動作します(少なくとも私が経験したMSVCでは動作します)。ただ、型推論とはあまり相性がよくありません。