(注意: 正如标签中已经清楚的那样,这是严格的 C++ 03. 是的,我知道,lambda会让所有这些痛苦消失(带来新的种类,我打赌),但这是一个嵌入式系统,有一个90年代的操作系统版本,我被告知我应该很高兴我有一个C++ 03编译器(GCC4.1.x,BTW)或C++编译器.所以请不要发布C++ 11解决方案,无需擦它,真的.
另外,std::bind(),std::function()等等,当然,实际std::tr1的,但我编辑了的 tr1前缀,因为我认为这增加了大多只有噪声的代码.)
我有一些类似服务器的东西,我需要注册函数,我需要调整它们来调用一些对象类似但略有不同的函数.这些函数具有不同的参数列表.服务器"知道"当我尝试注册一个函数时,它只接受一个具有正确签名的函数(根据std::function需要正确),这取决于作为模板参数传入的一些魔术标记.
这是代码的草图:
// this I just use
class server {
public:
template<unsigned int MagicTag>
bool register_call(typename some_traits_type<MagicTag>::func_type);
};
// this needs to be called from the server
class X {
public:
bool foo();
bool bar(std::string&);
bool baz(int);
};
// this is the glue
class Y {
public:
Y(X& x) : x_(x) {
register_call<MAGIC_FOO>(&Y::foo );
register_call<MAGIC_BAZ>(&Y::bar, _1);
register_call<MAGIC_FBZ>(&Y::baz, _1); …Run Code Online (Sandbox Code Playgroud) 由于我上一个最近的问题不幸地措辞并导致解决另一个问题然后我的,我将在这里尝试以明确的方式制定我的实际问题.
在我们开始之前,作为旁注,我正在将Javascript引擎V8集成到我的C++应用程序中.这就是示例中所有类型的来源.这也是我最终需要一个原始函数指针这一事实的原因.但我在下面详细说明.
从类内部我需要将带有capture子句的lambda表达式[=]作为该类型的参数传递std::function给另一个函数,并将其转换为原始函数指针.
在此代码中,InvocationCallback只是具有签名的函数的typedef Handle<Value>(Arguments const &).
typedef Handle<Value> (*InvocationCallback)(Arguments const &);
void Bind(string Name, function<Handle<Value>(Arguments const &)> Function)
{
InvocationCallback* function = Function.target<InvocationCallback>();
}
Run Code Online (Sandbox Code Playgroud)
所有lambda表达式也具有相同的签名.请注意,在此示例中与此Handle<String>兼容Handle<Value>.它也是由Javascript引擎V8提供的.
Bind("name", [=](const Arguments& args) -> Handle<Value>{
Handle<String> result = String::New(Name().c_str());
return result;
});
Run Code Online (Sandbox Code Playgroud)
C++允许我将此lambda传递std::function给上面的函数.但是我猜一个lambda表达式也存储了对它引用的对象的引用.不知何故[=]必须实现指定的访问.这可能是导致std::function原始函数指针失败的原因.
InvocationCallback* function = Function.target<InvocationCallback>();
Run Code Online (Sandbox Code Playgroud)
既没有编译时错误也没有运行时错误,但调试器告诉我它导致空指针.但我需要原始函数指针进行进一步处理.我想我可以std::bind在引用或this-pointer 之后转换lambda .
更新:由于似乎不可能将状态从lambda中取出,这就是我尝试过的.它编译但是function出来是一个空指针.
Bind("name", this, [](Base* object, const Arguments& args) …Run Code Online (Sandbox Code Playgroud) 我正在尝试将非静态类成员绑定到标准WNDPROC函数.我知道我可以通过使类成员静态来做到这一点.但是,作为一名C++ 11 STL学习者,我对使用<functional>标题下的工具非常感兴趣.
我的代码如下.
class MainWindow
{
public:
void Create()
{
WNDCLASSEXW WindowClass;
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.style = m_ClassStyles;
WindowClass.lpfnWndProc = std::function<LRESULT(HWND, UINT, WPARAM, LPARAM)>
( std::bind(&MainWindow::WindowProc,
*this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4));
WindowClass.cbClsExtra = 0;
WindowClass.cbWndExtra = 0;
WindowClass.hInstance = m_hInstance;
WindowClass.hIcon = LoadIconW(m_hInstance, MAKEINTRESOURCEW(IDI_WINDOW));
WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WindowClass.hbrBackground = (HBRUSH) COLOR_WINDOW;
WindowClass.lpszMenuName = MAKEINTRESOURCEW(IDR_MENU);
WindowClass.lpszClassName = m_ClassName.c_str();
WindowClass.hIconSm = LoadIconW(m_hInstance, MAKEINTRESOURCEW(IDI_WINDOW_SMALL));
RegisterClassExW(&WindowClass);
m_hWnd = CreateWindowEx(/*_In_ DWORD*/ ExtendedStyles,
/*_In_opt_ LPCTSTR*/ m_ClassName.c_str(),
/*_In_opt_ LPCTSTR*/ m_WindowTitle.c_str(),
/*_In_ …Run Code Online (Sandbox Code Playgroud) 是否可以使用std :: async调用使用std :: bind创建的函数对象.以下代码无法编译:
#include <iostream>
#include <future>
#include <functional>
using namespace std;
class Adder {
public:
int add(int x, int y) {
return x + y;
}
};
int main(int argc, const char * argv[])
{
Adder a;
function<int(int, int)> sumFunc = bind(&Adder::add, &a, 1, 2);
auto future = async(launch::async, sumFunc); // ERROR HERE
cout << future.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误是:
没有用于调用'async'的匹配函数:忽略候选模板:替换失败[使用Fp = std :: _1 :: function&,Args = <>]:'std :: _1 :: __ invoke_of中没有名为'type'的类型 …
我试图弄清楚当与闭包结合使用时std :: function引擎盖下发生了什么.我还无法绕过它,例如:正在调用什么构造函数?任何人都可以发布一个简单的drop的工作示例来替换std :: function,它支持以下示例中所需的功能吗?
#include <functional>
int main(int argc, char* argv[])
{
int mybool = 5;
auto foo = [&] (int arg) {
return mybool * arg;
};
std::function<int(int)> foo2 = foo;
int result = foo2(42);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我一直在使用Loki的Functor,我最近问了一个关于它的问题(仍然没有答案......)我被告知要使用std :: function,但我更喜欢Loki的Functor实现,因为它也适用于各种各样的指针作为参数(例如std :: shared_ptr).
struct Toto
{
void foo( int param )
{
std::cout << "foo: " << param << std::endl;
}
};
int
main( int argc, const char** argv )
{
std::shared_ptr<Toto> ptr = std::make_shared<Toto>();
Loki::Functor<void, LOKI_TYPELIST_1(int)> func( ptr, &Toto::foo );
func(1);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法用std :: function做到这一点?
我正在为我的程序编写一个小UI.我有方法onMouseMotion(),我可以用两种方式之一调用(参见代码); 如果我通过它std::function,那么!=for循环停止条件中的运算符会产生运行时异常vector iterators incompatible.为什么?
class Widget : public EventHandler
{
protected:
/* ... */
std::vector<Widget *> children_;
std::function<bool(Event &)> func_;
private:
bool onMouseMotion(Event &event);
/* ... */
};
Widget::Widget()
{
/* ... */
func_ = std::bind(&Widget::onMouseMotion, this, std::placeholders::_1);
/* ... */
}
bool Widget::processEvent(Event &event)
{
if (event.getType() == ui::EventType::MouseMotionEvent) {
/* Method 1 - onMouseMotion works ok */
onMouseMotion(event);
/* Method 2 - onMouseMotion throws */
//func_(event);
return true;
}
} …Run Code Online (Sandbox Code Playgroud) 有没有办法从lambda恢复类型信息,默认参数存储在std :: function中,该类型的参数中没有这些参数?
std::function<void()> f1 = [](int i = 0){};
std::function<void(int)> f2 = [](int i = 0){};
std::function<void(int)> f3 = f1; // error
std::function<void()> f4 = f2; // error
Run Code Online (Sandbox Code Playgroud)
查看std :: function的复制构造函数,其他函数类型没有部分模板特化,所以我想这个信息会丢失,只是你不能将一种类型的函数赋值给一个函数另一种类型,即使在内部它们都可以调用该函数.它是否正确?是否有任何解决方法可以实现这一目标?我正在看std :: function :: target,但没有运气,我不是函数类型和指针的专家.
另外,f1(或lambda)如何绑定默认参数?
c++ lambda function-pointers default-parameters std-function
显然std::function::operator=(F &&f)是需要的行为完全一样std::function(std::forward<F>(f)).swap(*this);.
除非我遗漏了某些东西,否则这个定义会导致一些多余的移动:
#include <functional>
#include <iostream>
struct A
{
A() {std::cout << "A()\n";}
A(const A &) {std::cout << "A(const A &)\n";}
A(A &&) {std::cout << "A(A &&)\n";}
A &operator=(const A &) {std::cout << "A &operator=(const A &)\n"; return *this;}
A &operator=(A &&) {std::cout << "A &operator=(A &&)\n"; return *this;}
~A() {std::cout << "~A()\n";}
void operator()() const {}
};
int main()
{
std::function<void()> f;
f = A{};
}
Run Code Online (Sandbox Code Playgroud)
打印:
Run Code Online (Sandbox Code Playgroud)A() // Created by `A{}` …
我发现,将lambda函数转换为std::function<>值的相对少量代码的编译时间可能非常高,特别是对于Clang编译器.
考虑以下创建100个lambda函数的虚拟代码:
#if MODE==1
#include <functional>
using LambdaType = std::function<int()>;
#elif MODE==2
using LambdaType = int(*)();
#elif MODE==3
#include "function.h" // https://github.com/skarupke/std_function
using LambdaType = func::function<int()>;
#endif
static int total=0;
void add(LambdaType lambda)
{
total += lambda();
}
int main(int argc, const char* argv[])
{
add([]{ return 1; });
add([]{ return 2; });
add([]{ return 3; });
// 96 more such lines...
add([]{ return 100; });
return total == 5050 ? 0 : 1;
}
Run Code Online (Sandbox Code Playgroud)
根据MODE预处理器宏,该代码可以在以下三种方式之间进行选择,以便通过lambda函数传递 …