我正在尝试创建Don Clugston的成员函数指针和最快可能的C++代表的C++ 11实现,并使其成为std::function替代品.
我像这样构造lambda FastDelegates:
// FastFunc is my name for FastDelegate
template<typename LambdaType> FastFunc(LambdaType lambdaExpression)
{
this->m_Closure.bindmemfunc(&lambdaExpression, &LambdaType::operator());
}
Run Code Online (Sandbox Code Playgroud)
现在,一些测试:
FastFunc<void()> test = []{ std::cout << "hello" << std::endl; };
test();
// Correctly prints "hello"
bool b{false};
FastFunc<void()> test2 = [&b]{ std::cout << b << std::endl; };
test2();
// Crash!
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,当lambda是"微不足道的"(没有捕获)时,按值复制并获取其地址是有效的.但是当lambda存储某种状态(捕获)时,我不能只按值将其复制到FastFunc.
我尝试通过引用获取lambda,但是当它像示例中的临时时我不能这样做.
我必须以某种方式将 lambda 存储在其中FastFunc,但我不想使用std::shared_ptr因为它很慢(我尝试了一个使用它的不同fastdelegate实现,并且它的性能可比std::function).
我怎样才能让我实现Don Clugston最快的C++代表与lambdas一起工作,捕获状态,保持fastdelegates的惊人表现?
我是C++的新手,我正在学习lambdas,functor和callables,我知道有一个包装类,即std::function允许存储和调用不同类型的callables(只要具有相同的调用签名,或功能类型).
现在,我明白你可以使用函数类型参数来实现函数指针参数,如下所示:
void fun(int,int*(int,int&));
Run Code Online (Sandbox Code Playgroud)
它只不过是一个函数,它接受一个int函数指针和一个函数指针int *f(int,int&),即使该语言允许我将函数作为参数传递(带或不带符号).事实上,函数参数列表也可能写成:
void fun(int,int*(*)(int,int&));
Run Code Online (Sandbox Code Playgroud)
现在,回到std::function类型
我知道我可以std::function使用函数类型进行实例化,并允许将任何类型的可调用函数传递给包装器.但是,函数类型不是我可以在任何实例化中用作模板类型参数的类型,例如:
std::vector<int(int)> f_vec;
Run Code Online (Sandbox Code Playgroud)
相反,我应该制作一个函数指针的向量
std::vector<int(*)(int)> f_vec;
Run Code Online (Sandbox Code Playgroud)
这将允许我插入指向函数的指针,但不能插入函子或lambda.
所以,我的问题是,如何使用类型参数实例化模板,如函数类型?在库std::function类型的引擎盖下发生了什么.我的意思是一个函数类型在我看来是一个我不能在模板中使用的类型?请求你能让事情变得更加清晰,因为我刚开始学习这些话题.谢谢
有没有办法从std :: map指向构造函数?我想用我想要使用的代码执行以下操作,#if 0但我似乎无法使其工作:
#include <map>
#include <functional>
using namespace std;
class Base { };
class A : public Base { };
class B : public Base { };
enum class Type { A, B, };
#if 0
using type_map_t = std::map<Type, std::function<Base*()>>;
type_map_t type_map = {
{Type::A, &A::A},
{Type::B, &B::B},
};
#endif
Base*
getBase(Type t)
{
#if 0
auto constructor = type_map[t];
return constructor();
#else
switch(t)
{
case Type::A:
return new A();
case Type::B:
return new B(); …Run Code Online (Sandbox Code Playgroud) 这是一个玩具的例子
#include <iostream>
#include <functional>
struct Obj
{
int x;
int foo()
{
return 42;
}
};
int main()
{
Obj a, b;
std::function<int()> f1 = std::bind(&Obj::foo, &a);
std::function<int()> f2 = std::bind(&Obj::foo, &b);
std::function<int()> f3 = std::bind(&Obj::foo, &a);
std::function<int()> f4 = std::bind(&Obj::foo, &b);
}
Run Code Online (Sandbox Code Playgroud)
我如何验证,f1 == f3并且f2 == f4,==比较器在这里,这意味着两个std::function对象对应于同一对象的相同方法?
我想std::function从lambda创建一个,在 a 中template,它将所需的实例std::function作为其参数:
template <class functionT>
functionT make_lambda() {
return [](/* ignore all args */){ std::cout << "my lambda\n"; };
}
Run Code Online (Sandbox Code Playgroud)
然后调用template具有不同别名的std::function:
using function_no_args = std::function<void(void)>;
using function_args = std::function<void(int)>;
make_lambda<function_no_args>()(); // output: "my lambda"
make_lambda<function_args>()(999); // compile error
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
一些精度:
std::function,在traits结构中定义它们并将它们传递给我的代码的多个部分void,只有参数可能会改变std::function它本身提供了一个很好的实用程序——它提供了类型擦除,以便一般地存储/提供对可调用项的访问。它的灵活性非常好:
#include <functional>
#include <iostream>
void printer() {
std::cout << "I print!";
}
int adder(int a, int b) {
return a + b;
}
int main() {
std::function<void()> fun1 = printer; // fun1() calls printer()
std::function<int(int, int)> fun2 = adder; // fun2(1, 2) calls adder(1, 2)
std::function<void()> fun3 = [](){}; // fun3() will do nothing - same for the lambda
std::function<int(int, int)> fun4 =
[](int a, int b) { return a + b; }; // fun4(1, 2) will yield …Run Code Online (Sandbox Code Playgroud) 我试过这个
{
std::function<void(int)> push;
queue<int> myqueue;
push = std::bind(static_cast<void (queue<int>::*)(int)>(&queue<int>::push), &myqueue,std::placeholders::_1);
push(8);
}
Run Code Online (Sandbox Code Playgroud)
但它不起作用
当 astd::function被复制时,它引用的代码指令是否也被复制?
Anstd::function是通过某种形式的 callable 初始化的,它以某种方式指向可执行代码(就像函数指针通常所做的那样)。现在,当一个函数对象被复制时,这个可执行代码运行时是复制的还是内部引用的?重新表述这个问题:如果std::function复制了一个实例,那么内存中是否有多个相同编译代码指令的副本?是std::function实际存储函数代码的对象还是函数指针的抽象?
前者看起来很浪费,我不怀疑,但到目前为止我在这个主题上发现的一切要么太模糊,要么太具体,我无法肯定地说。例如
当目标是函数指针或 std::reference_wrapper 时,保证小对象优化,即这些目标总是直接存储在 std::function 对象内,不会发生动态分配。其他大对象可以在动态分配的存储中构造并由 std::function 对象通过指针访问。- cppreference
给出了一些关于它是如何完成的提示,但似乎仍然太模糊,并且可能与这个问题根本没有关系,因为std::function.
对于上下文:我正在尝试重构一些糟糕的 C 语言代码,这些代码将输入事件(击键、鼠标输入等)映射到特定行为,该行为在目标数据结构上执行,该数据结构可以被程序解释为更多具有除击键之外的语义上下文的特定输入(又名键绑定)。人们可以怀疑行为的要求变化很大。
这之前是通过定义和数字列表来实现的,这些列表指定了 input-event-ids,以及由 switch-case 选择的硬编码行为。我们很快接近了这种最初的做法变得笨拙的边界。
为了摆脱已定义的列表,实现可扩展的、声明性的、面向对象的和灵活的设计,我考虑了高阶函数。
特别是由于某些行为非常简单且需要重复使用(例如切换输出数据结构中的一个值),而其他行为在附加多个条件的情况下更加复杂,我想静态声明一些行为,但仍然会在某些情况下,喜欢只分配一些特殊的 lambda。由于我需要存储每个输入的行为(键、鼠标按钮、鼠标轴等),并且可能一次针对不同的键绑定集实例化一种特定行为类型的多个副本,我想知道是否应该引用这种行为,而不是按值存储。在前一种情况下,新的 lambdas 需要由行为结构拥有,但静态声明的行为不需要,这在实际中会导致一些shared_ptr恶作剧。在后一种情况下,根据价值,这不是问题,但我不希望例如切换行为的多个副本导致过多的冗余开销。
在下面的代码中,为什么std::function<void (X)>允许绑定到函数void f(X&&)?
#include <functional>
struct X {};
void f1(X x) {}
void f2(X& x) {}
void f3(const X&) {}
void f4(X&& x) {}
int main()
{
X x;
f1(x); // ok
f2(x); // ok
f3(x); // ok
// f4(x); // doesn't compile
std::function<void (X)> ff1(f1); // ok
//std::function<void (X)> ff2(f2); // doesn't compile
std::function<void (X)> ff3(f3); // ok
std::function<void (X)> ff4(f4); // ok... why?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么允许这样做背后的直觉是std::function什么,它将如何由 实现,以及当您将左值参数传递给std::function,然后调用接受右值引用的函数时,这实际上意味着什么?
请考虑以下代码示例:
#include <functional>
#include <iostream>
template <typename... Ts>
class SomeClass
{
public:
std::function<bool(Ts...)> some_func;
void run(Ts... args)
{
this->some_func(args...); // this works
this->thread_run((void *)&this->some_func, args); // this won't work, can't pass the parameter pack
}
static void thread_run(void *func_ptr, void *args_ptr)
{
auto thread_func = *(std::function<bool(Ts...)> *)(func_ptr);
thread_func(2, 3);
}
};
int main()
{
SomeClass<int, int> a;
a.some_func = [](int x, int y)
{ std::cout << "Arguments: " << x << " " << y << std::endl; return x > …Run Code Online (Sandbox Code Playgroud)