将值 caputring lambda 传递给需要函数指针的函数
Passing a value caputring lambda to a function which expects a function pointer
我有一个 class foo
,我想向其传递类型 T
的对象以及带有签名 void (T)
的“类删除器”函数。目前我将这个函数存储为 typedef void (*bar_t)(T);
类型的对象 m_bar
inside foo
.
只要我要使用的函数与上述签名完全匹配,这就没有问题。但是,如果所需的函数有一个附加参数,并且我需要将一个特定的非常量值传递给它,我会尝试传递一个 lambda 函数,该函数按值捕获该值;但现在我在下面的示例代码中收到编译器错误 cannot convert from 'initializer list' to 'foo<int>'
:
`
template<typename T>
struct foo
{
typedef void (*bar_t)(T);
foo(T t, bar_t bar)
: t(t),
bar(bar)
{}
~foo() { bar(t); }
T t;
bar_t bar;
};
void bar1(int x) {}
void bar2(int* x) {}
void bar3(int, int* x) {}
template<typename T, class Bar>
foo<T> make_foo(T t, Bar bar) { return { t, bar }; }
int main()
{
int x = 47, y = 0;
foo f1(x, bar1);
foo f2(x, [](int x) { bar2(&x); });
auto f3a = make_foo(x, [y](int x) { bar3(0, &x); }); // ok
auto f3b = make_foo(x, [y](int x) { bar3(y, &x); }); // compiler error
}
我们可以在不在 foo
中存储 std::function
的情况下解决这个问题吗?
你基本上有两个选择:
添加额外的模板参数:
template<typename T, typename DeleterLike>
struct foo
{
using bar_t = DeleterLike;
foo(T t, bar_t bar)
: t(t),
bar(bar)
{}
~foo() { bar(t); }
T t;
bar_t bar;
};
对类型使用一些类型擦除(如std::function
)
template<typename T>
struct foo
{
using bar_t = std::function<void(const T&)>;
foo(T t, bar_t bar)
: t(t),
bar(bar)
{}
~foo() { bar(t); }
T t;
bar_t bar;
};
在编译时知道 y
值的非常有限的情况下,这有效:
template <typename T>
struct foo
{
typedef void (*bar_t)(T);
foo(T t, bar_t bar) : t(t), bar(bar) {}
~foo() { bar(t); }
T t;
bar_t bar;
};
template <typename T, typename Y, Y y>
auto create_lambda()
{
return [](T x) { std::cout << x + y << "\n"; };
}
int main()
{
foo<double> f1(1.5, create_lambda<double, int, 1>());
foo<double> f2(1.5, create_lambda<double, int, 2>());
}
并打印
3.5
2.5
我有一个 class foo
,我想向其传递类型 T
的对象以及带有签名 void (T)
的“类删除器”函数。目前我将这个函数存储为 typedef void (*bar_t)(T);
类型的对象 m_bar
inside foo
.
只要我要使用的函数与上述签名完全匹配,这就没有问题。但是,如果所需的函数有一个附加参数,并且我需要将一个特定的非常量值传递给它,我会尝试传递一个 lambda 函数,该函数按值捕获该值;但现在我在下面的示例代码中收到编译器错误 cannot convert from 'initializer list' to 'foo<int>'
:
`
template<typename T>
struct foo
{
typedef void (*bar_t)(T);
foo(T t, bar_t bar)
: t(t),
bar(bar)
{}
~foo() { bar(t); }
T t;
bar_t bar;
};
void bar1(int x) {}
void bar2(int* x) {}
void bar3(int, int* x) {}
template<typename T, class Bar>
foo<T> make_foo(T t, Bar bar) { return { t, bar }; }
int main()
{
int x = 47, y = 0;
foo f1(x, bar1);
foo f2(x, [](int x) { bar2(&x); });
auto f3a = make_foo(x, [y](int x) { bar3(0, &x); }); // ok
auto f3b = make_foo(x, [y](int x) { bar3(y, &x); }); // compiler error
}
我们可以在不在 foo
中存储 std::function
的情况下解决这个问题吗?
你基本上有两个选择:
添加额外的模板参数:
template<typename T, typename DeleterLike> struct foo { using bar_t = DeleterLike; foo(T t, bar_t bar) : t(t), bar(bar) {} ~foo() { bar(t); } T t; bar_t bar; };
对类型使用一些类型擦除(如
std::function
)template<typename T> struct foo { using bar_t = std::function<void(const T&)>; foo(T t, bar_t bar) : t(t), bar(bar) {} ~foo() { bar(t); } T t; bar_t bar; };
在编译时知道 y
值的非常有限的情况下,这有效:
template <typename T>
struct foo
{
typedef void (*bar_t)(T);
foo(T t, bar_t bar) : t(t), bar(bar) {}
~foo() { bar(t); }
T t;
bar_t bar;
};
template <typename T, typename Y, Y y>
auto create_lambda()
{
return [](T x) { std::cout << x + y << "\n"; };
}
int main()
{
foo<double> f1(1.5, create_lambda<double, int, 1>());
foo<double> f2(1.5, create_lambda<double, int, 2>());
}
并打印
3.5
2.5