可变参数 lambda 捕获的解决方法
Workaround for variadic lambda capture
我在这里看到了一些与在lambda中捕获可变参数的gcc错误有关的问题。例如,请参阅:lambda 捕获是否支持可变参数模板参数或编译器错误或非标准代码?- λ中的可变参数模板捕获。我有以下人为的例子来说明我正在尝试做的事情
#include <iostream>
#include <functional>
class TestVariadicLambda {
public:
template<typename... Args>
std::function<void()> getFunc(Args... args) {
return [=]{ printArgs(args...); };
}
template<typename T, typename... Args>
void printArgs(T value, Args... args) {
std::cout << value << ", ";
printArgs(args...);
}
void printArgs() {std::cout << "n";}
};
在 gcc 4.8.2 中,我收到以下错误:
../src/TestVariadicLambda.h: In lambda function:
../src/TestVariadicLambda.h:9:25: error: parameter packs not expanded with ‘...’:
return [=]{ printArgs(args...); };
^
../src/TestVariadicLambda.h:9:25: note: ‘args’
../src/TestVariadicLambda.h:9:29: error: expansion pattern ‘args’ contains no argument packs
return [=]{ printArgs(args...); };
^
我的问题是我该如何解决这个问题,因为它在 gcc4.8 中不起作用
以下内容将起作用。
#include <iostream>
#include <functional>
#include <vector>
std::string to_string(const char* s)
{
return s;
}
class Test
{
private:
void print() {}
public:
template<typename T, typename... Args>
void print(T value, Args... args)
{
std::cout << value << "n";
print(args...);
}
template<typename... Args>
std::function<void()> getFunc(Args... args)
{
using namespace std;
std::vector<std::string> ArgumentList;
std::initializer_list<int> {(ArgumentList.push_back(to_string(args)), 0)...};
return [=] {for (const auto &t : ArgumentList){print(t);}};
}
};
int main()
{
Test().getFunc("Hey", 1, 2, 3.0f)();
}
这是一个至少在GCC 4.8.0上静态工作的解决方法(也应该适用于VisualStudio和clang)
(代码主要来自这个答案,我所做的是将参数包装在元组中,然后使用元组作为旁路)
#include <iostream>
#include <functional>
#include <tuple>
using namespace std;
// ------------- UTILITY---------------
template<int...> struct index_tuple{};
template<int I, typename IndexTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
template<class Ret, class... Args, int... Indexes >
Ret apply_helper( Ret (*pf)(Args...), index_tuple< Indexes... >, tuple<Args...>&& tup)
{
return pf( forward<Args>( get<Indexes>(tup))... );
}
template<class Ret, class ... Args>
Ret apply(Ret (*pf)(Args...), const tuple<Args...>& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(), tuple<Args...>(tup));
}
template<class Ret, class ... Args>
Ret apply(Ret (*pf)(Args...), tuple<Args...>&& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(), forward<tuple<Args...>>(tup));
}
/// ------------------- REAL CODE --------
void printArgs() {std::cout << "n";}
template<typename T, typename... Args>
void printArgs(T value, Args... args) {
std::cout << value << ", ";
printArgs(args...);
}
template<typename... Args>
std::function<void()> getFunc(Args... args) {
std::tuple<Args...> tup(args...);
return [=]{ apply<void, Args...>(printArgs, tup); };
}
int main(){
auto f = getFunc<int,float,const char*>(4,5.4f,"hello");
f();
return 0;
}
另外,为什么不使用std::bind?基本上 std::bind 可以用您想要的参数为您创建一个 lambda(只是语法糖,为您选择最可行的方式:)
相关文章:
- 有没有办法在 c++ 中同时生成随机数?如果没有,是否有解决方法?
- 从 int 中剥离位时,编译器会警告一个转换,但不警告其他转换.有解决方法吗?
- 是否有解决方法可以在 c++ 中为 short 定义用户定义的文字?
- 不为 emplace() 定义构造函数的解决方法
- 删除复制构造函数的 Intel 13.1.2 中不良C++行为的解决方法
- 函数模板部分专业化-有什么解决方法吗
- 带boost的过载模糊性:可选,解决方法
- 继承构造函数和其他变量的解决方法
- C++ 解决方法:"从类型"B*"的表达式初始化类型"C*&"的引用无效"
- 对前向声明类型进行unique_ptr的解决方法
- 解决方法:'can not be used when making a shared object; recompile with -fPIC'使用Cmake。使用普通的 g++ 工作
- 解决方法:QPixmap:在GUI线程之外使用pixmap是不安全的
- CreateProcessWithTokenW 的 cmdline 参数的最大长度是否有解决方法?
- C++双精度作为模板参数的解决方法
- 在参数相关查找之前进行模板替换的任何方法(或解决方法?
- CUDA 内核"Only a single pack parameter is allowed"解决方法?
- dlsym() 解决方法返回类型
- VS2017是否有VLA(可变长度阵列)支持解决方法
- 解决方法:未定义对"class::function"的引用
- 来自 Boost 的 JSON 解析器的警告 C4512 的解决方法