【问题标题】:Move (or copy) capture variadic template arguments into lambda移动(或复制)捕获可变参数模板参数到 lambda
【发布时间】:2021-10-06 14:37:32
【问题描述】:

我试图弄清楚如何将可变参数参数移动(或者如果移动不可用,则仅复制)到模板函数中的 lambda。

我正在使用仅移动类(见下文)对此进行测试,因为这将是需要与我的模板一起使用的“最坏情况”。

class MoveOnlyTest {
public:
    MoveOnlyTest(int a, int b = 20, int c = 30) : _a(a), _b(b), _c(c) {
        std::cout << "MoveOnlyTest: Constructor" << std::endl;
    }
    
    ~MoveOnlyTest() {
        std::cout << "MoveOnlyTest: Destructor" << std::endl;
    }
    
    MoveOnlyTest(const MoveOnlyTest& other) = delete;

    MoveOnlyTest(MoveOnlyTest&& other) :
        _a(std::move(other._a)),
        _b(std::move(other._b)),
        _c(std::move(other._c))
    {
        std::cout << "MoveOnlyTest: Move Constructor" << std::endl;
        
        other._a = 0;
        other._b = 0;
        other._c = 0;
    }
    
    MoveOnlyTest& operator=(const MoveOnlyTest& other) = delete;

     MoveOnlyTest& operator=(MoveOnlyTest&& other) {
        if (this != &other) {
            _a = std::move(other._a);
            _b = std::move(other._b);
            _c = std::move(other._c);
            
            other._a = 0;
            other._b = 0;
            other._c = 0;
        
            std::cout << "MoveOnlyTest: Move Assignment Operator" << std::endl;
        }
        
        return *this;
    }
    
    friend std::ostream& operator<<(std::ostream& os, const MoveOnlyTest& v) {
        os << "{a=" << v._a << "}";
        return os;
    }
    
private:
    int _a;
    int _b;
    int _c;
};

这是我尝试开始工作的测试代码:

void test6() {
    std::cout << "--------------------" << std::endl;
    std::cout << "       TEST 6       " << std::endl;
    std::cout << "--------------------" << std::endl;
    
    MoveOnlyTest v(1, 2, 3);
    
    test6_A(std::move(v));
}

void test6_A(MoveOnlyTest v) {
    std::cout << "test6_A()" << std::endl;
    
    test6_B(test6_C, v);
}

template <typename ... ARGSF, typename ... ARGS>
void test6_B(void(*fn)(ARGSF...), ARGS&&... args) {
    std::cout << "test6_B()" << std::endl;
    
    //What do I need to get args to be moved/copied into the lambda
    auto lambda = [fn, args = ???]() mutable {
        (*fn)( std::forward<ARGS>(args)... );
    };
    
    lambda();
}

void test6_C(MoveOnlyTest v) {
    std::cout << "test6_C()" << std::endl;
    
    std::cout << "v = " << v << std::endl;
}

我试图获得与下面完全相同的行为,仅使用通用模板,以便我可以创建一个捕获和参数的 lambda,并使用这些参数调用任何函数。

void test5() {
    std::cout << "--------------------" << std::endl;
    std::cout << "       TEST 5       " << std::endl;
    std::cout << "--------------------" << std::endl;
    
    MoveOnlyTest v(1, 2, 3);
    
    test5_A(std::move(v));
}

void test5_A(MoveOnlyTest v) {
    std::cout << "test5_A()" << std::endl;
    
    auto lambda = [v = std::move(v)]() mutable {
        test5_B(std::move(v));
    };
    
    lambda();
}

void test5_B(MoveOnlyTest v) {
    std::cout << "test5_B()" << std::endl;
    
    std::cout << "v = " << v << std::endl;
}

明确地说,我不想c++ lambdas how to capture variadic parameter pack from the upper scope那样完美地捕捉参数,如果可能,我想移动它们,如果没有,复制它们(原因是我计划存储这个 lambda 供以后执行,因此如果它们只是通过引用捕获,堆栈中的变量将不再存在)。

【问题讨论】:

  • args = std::move(args)?
  • @NathanOliver 不。这会导致“参数包不使用 '...' 展开”
  • 应该先test6_B(test6_C, std::move(v));

标签: c++ lambda c++17 move


【解决方案1】:

明确地说,我不想像在 c++ 中那样完美地捕获参数 lambdas 如何从上层范围捕获可变参数包 I 如果可能的话想移动它们

使用相同的形式:

auto lambda = [fn, ...args = std::move(args)]() mutable {
  (*fn)(std::move(args)...);
};

在 C++17 中,你可以这样做:

auto lambda = [fn, args = std::tuple(std::move(args)...)]() mutable {
  std::apply([fn](auto&&... args) { (*fn)( std::move(args)...); }, 
             std::move(args));
};

【讨论】:

  • 我很好奇,这是否适用于 C++17。我尝试这样做并得到错误“'...'之前的预期标识符”
  • @PatrickWright。这是一个 C++20 特性。
猜你喜欢
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
  • 2017-12-17
  • 2016-12-01
  • 2012-04-09
  • 1970-01-01
相关资源
最近更新 更多