请考虑以下代码:
#include <functional>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <time.h>
struct Foo {
Foo(int x) : x(x) {}
void func1() const { printf("Foo::func1 x=%d\n", x); }
void func2() const { printf("Foo::func2 x=%d\n", x); }
int x;
char junk[64];
};
struct Bar {
Bar(int x) : x(x) {}
void func3() const { printf("Bar::func3 x=%d\n", x); }
int x;
char junk[64];
};
void loop(std::function<void()>& g) {
for (int i=0; i<10; ++i) {
switch (rand()%3) {
case 0:
{
Foo foo(3);
g = std::bind(&Foo::func1, foo);
break;
}
case 1:
{
Foo foo(4);
g = std::bind(&Foo::func2, foo);
break;
}
case 2:
{
Bar bar(5);
g = std::bind(&Bar::func3, bar);
break;
}
default: break;
}
}
}
int main() {
srand(time(NULL));
std::function<void()> g;
loop(g);
g();
return 0;
}
此代码将使用复制的对象实例(已超出范围)执行Foo::func1()
,Foo::func2()
或Bar::func3()
中的一个。
我想要使用此代码更改的内容是删除loop()
中的动态分配。为此,我尝试在std::function
周围创建一个包装器,如下所示:
template <typename _Signature> class my_function;
template <typename R, typename... Args>
class my_function<R(Args...)> {
public:
template<typename T, typename FUNC>
void bind(FUNC&& func, const T& t) {
static_assert(sizeof(t) <= sizeof(obj_buffer), "insufficient obj_buffer size");
static_assert(std::is_trivially_destructible<T>::value, "memory leak");
auto p = new(obj_buffer) T(t); // placement new
auto ref = std::ref(*p);
f = std::bind(func, ref /* how do I forward variable # of placeholders here??? */);
}
R operator()(Args&& ...args) const { return f(std::forward<Args>(args)...); }
private:
char obj_buffer[1024];
std::function<R(Args...)> f;
};
然后我将g
的声明从std::function<void()>
更改为my_function<void()>
,并将g = std::bind(x,y)
声明替换为g.bind(x,y)
loop()
内的std::bind
声明。代码编译并按预期工作。
我有两个不同的问题:
标准是否保证我们在此避免动态内存分配?用户Jarod42告诉我,它使用匿名lambda在一个非常相似的setting中,但我不确定f
是否同样存在。
当我有一个非空模板参数包参数bind()
时,如何在Args
函数中实例化Args
?我的代码不会为非空max_execution_time = 600
编译。