这个指针捕获在lambda包装器周围的递归函数 [英] This-pointer capture in lambda wrapper around recursive function

查看:248
本文介绍了这个指针捕获在lambda包装器周围的递归函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类模板 Wrap< T> 使用递归成员函数 test(int)传递给具有lambda( std :: accumulate 在下面的代码)的STL算法。

I have a class template Wrap<T> with a recursive member function test(int) that I want to pass to an STL algorithm with a lambda (std::accumulate in the code below).

如果我使用默认捕获列表 = ,并使我的递归meber函数 static ,一切都很好,并得到我想要的结果。

If I use a default capture list of =, and make my recursive meber function static, all is fine and get the result I want.

但是,如果我使它成为非静态成员函数,Visual C ++和gcc 4.7.2都会抱怨一个单位化的 this -pointer,除非我将我的递归调用限定为 this-> test()

However, if I make it a non-static member function, both Visual C++ and gcc 4.7.2 complain about an unitialized this-pointer, unless I qualify my recursive call as this->test().

#include <algorithm>
#include <iostream>
#include <vector>

template<typename T>
struct Wrap 
{
   static int test1(int depth)
   {
      std::vector<int> v = { 0, 1, 2, 3 };
      return depth == 0? 1 : std::accumulate(v.begin(), v.end(), int(0), [=](int sub, int const&) {
         return sub + test1(depth - 1);
      });   
   }

   int test2(int depth)
   {
      std::vector<int> v = { 0, 1, 2, 3 };
      return depth == 0? 1 : std::accumulate(v.begin(), v.end(), int(0), [=](int sub, int const&) {
         return sub + /*this->*/test2(depth - 1);
      });   
   }   
};

int main()
{
   std::cout << Wrap<int>::test1(0) << "\n"; // 1
   std::cout << Wrap<int>::test1(1) << "\n"; // 4
   std::cout << Wrap<int>::test1(2) << "\n"; // 16

   Wrap<int> w;
   std::cout << w.test2(0) << "\n"; // 1
   std::cout << w.test2(1) << "\n"; // 4
   std::cout << w.test2(2) << "\n"; // 16
}

输出 LiveWorkSpace

source.cpp: In instantiation of 'int Wrap<T>::test2(int) [with T = int]':   
source.cpp:32:26:   required from here 
source.cpp:19:74: error: missing initializer for member 'Wrap<T>::test2(int) [with T = int]::<lambda(int, const int&)>::__this' [-Werror=missing-field-initializers]

取消注释 / * this-> / * piece,给出与静态成员函数相同的结果。

Uncommenting the /*this->/* piece, gives the same result as for the static member function.

为什么需要使用 this->

推荐答案

我相信这是GCC 4.7.2的错误。警告说:

I believe this is a bug of GCC 4.7.2. The warning says:

成员'Wrap< T> :: test2(int)缺少初始化器[with T = int] lambda(int,const int&)> :: __ this'

这意味着编译器识别

Which means that the compiler recognizes the this pointer is to be captured and the generated closure does contain a pointer for it, but that pointer does not get initialized in the closure's constructor.

#include <algorithm>
#include <iostream>
#include <vector>

template<typename T>
struct Wrap 
{
    int test2(int depth)
    {
        m_test++;
        std::vector<int> v = { 0, 1, 2, 3 };
        return depth == 0? 1 : std::accumulate(
             v.begin(), v.end(), int(0), [=](int sub, int const&) {
             return sub + /*this->*/test2(depth - 1);
             });   
    }

    int m_test = 0;
};

int main()
{
    Wrap<int> w;
    std::cout << w.test2(2) << "\n"; // 1
}

此代码使用Clang 3.2和VS2012进行编译,确认是否存在错误。

This code compiles fine with Clang 3.2 and VS2012, which seems to confirm the presence of a bug.

这篇关于这个指针捕获在lambda包装器周围的递归函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆