我想实现一个管理器,它使用C++ 11将回调存储到多态类的成员函数中.问题是我不知道如何处理成员所属的对象被删除或应该被删除的情况,我想让界面尽可能简单.
所以我想到了以下内容:将a存储std::weak_ptr到对象以及存储std::function到成员.
以下似乎有效:
class MyBase {
public:
MyBase() {}
virtual ~MyBase() {}
};
//--------------------------------------------------
class MyClass : public MyBase {
public:
MyClass() : MyBase() {}
void myDouble(double val) const { std::cout << "Value is: " << val << std::endl; }
};
//--------------------------------------------------
Class Manager {
public:
void setFunction(std::weak_ptr<MyBase> base, std::function<void(double)> func) {
m_function.first = base;
m_function.second = func;
}
private:
std::pair<std::weak_ptr<MyBase>, std::function<void(double)>> m_function;
};
Run Code Online (Sandbox Code Playgroud)
要使用它:
Manager db;
std::shared_ptr<MyClass> myClass = std::make_shared<MyClass>();
db.setFunction(myClass, std::bind(&MyClass::myDouble, myClass, std::placeholders::_1)); …Run Code Online (Sandbox Code Playgroud) 我正在玩std :: function和std :: bind,我注意到一些不直观的东西,我想更好地理解它.
例如:
void fun()
{
}
void hun(std::string)
{
}
int main()
{
function<void(int)> g = &fun; //This fails as it should in my understanding.
function<void(int)> f = std::bind(fun); //This works for reasons unknown to me
function<void(int, std::string)> h = std::bind(hun); //this doesn't work
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如何function<void(int)>将一个函数绑定到void().然后我可以调用f(1)并获得乐趣().我想了解这是如何完成的.进入微软Visual Studio 2012的实现,让我迷失在无法理解的宏观之中.所以这就是我在这里问这个问题的原因.
我正在玩,std::function并std::bind了解如何复制参数,如果我可以保存一些复制操作.
我理解在使用时std::bind,参数是通过值传递而不是引用(除非std::ref指定).但是,当我运行以下代码段时,复制构造函数被调用两次.有人可以解释原因吗?
struct token
{
static int i;
int code;
token()
: code(i++)
{
cout << __FUNCTION__ << ": " << code << endl;
}
virtual ~token()
{
cout << __FUNCTION__ << endl;
}
token (token const & other)
: code (other.code)
{
cout << "copy ctor: " << code << endl;
}
// update -- adding a move ctor
token (token const && other)
: code (std::move(other.code))
{
cout << "move …Run Code Online (Sandbox Code Playgroud) 有人可以推荐tr1的mem_fn和绑定工具的一些很酷的实际用途吗?我不需要深奥的c ++用于库开发.只是一些使用这些的应用程序级编码.
任何帮助将非常感激.
我正在尝试将一个rvalue引用绑定到一个lambda使用std::bind,但是当我把它扔进一个std::async调用时我遇到了问题:( 来源)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, std::string{"hello world"});
auto future = std::async(bound); // Compiler error here
future.get()
Run Code Online (Sandbox Code Playgroud)
这会发出编译器错误我不确定如何解释:
错误:'class std :: result_of(std :: basic_string)>&()>'中没有名为'type'的类型
这里发生了什么?有趣的是,稍微修改确实可以按预期编译和工作.如果我改为std::string{"hello world"}c字符串文字,一切正常:( 来源)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, "hello world");
auto future = std::async(bound);
future.get(); // Prints "hello world" as expected
Run Code Online (Sandbox Code Playgroud)
为什么这有效但不是第一个例子?
受此评论的启发,关于将lambda与rvalue引用参数直接std::async绑定到,通过std::async编译将rvalue绑定到lambda 并按预期执行:( 实例)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto future = std::async(lambda, std::string{"hello world"});
future.get();
Run Code Online (Sandbox Code Playgroud)
std::bind但是,使用会触发编译器错误:( 实例)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, std::string{"hello world"}); // Compiler error
bound();
Run Code Online (Sandbox Code Playgroud)
这是因为std::bind保持message为左值,因此当它将它传递给lambda时,参数不再与参数匹配.
我已经阅读了std::async内部使用的内容std::bind,那么当std::bind它没有时,如何使用rvalue引用参数?是否存在需要此行为的标准的特定部分,或者这取决于编译器?
我无法找到如何使用参数将参数绑定到重载函数std::bind.不知何故std::bind不能推断出重载类型(对于它的模板参数).如果我不重载该功能一切正常.代码如下:
#include <iostream>
#include <functional>
#include <cmath>
using namespace std;
using namespace std::placeholders;
double f(double x)
{
return x;
}
// std::bind works if this overloaded is commented out
float f(float x)
{
return x;
}
// want to bind to `f(2)`, for the double(double) version
int main()
{
// none of the lines below compile:
// auto f_binder = std::bind(f, static_cast<double>(2));
// auto f_binder = bind((std::function<double(double)>)f, \
// static_cast<double>(2));
// auto f_binder = bind<std::function<double(double)>>(f, \ …Run Code Online (Sandbox Code Playgroud) 我正在使用以下代码向我的 C++ 类添加信号处理:
namespace {
std::atomic<bool> signal_flag(false);
}
void terminate_or_interrupt_handler(int signal) {
switch (signal) {
case SIGTERM:
WARN("SIGTERM received");
signal_flag.store(true);
break;
case SIGINT:
WARN("SIGINT received");
signal_flag.store(true);
break;
default:
throw (std::runtime_error("Unhandled signal received"));
}
}
signal(SIGTERM, &terminate_or_interrupt_handler);
Run Code Online (Sandbox Code Playgroud)
此代码有效,但它需要在与信号标志变量相同的范围内定义信号处理函数。我决定修改代码并将通过signal_flag引用传递给函数并用于std::bind将处理程序“专门化”到我的类。
void terminate_or_interrupt_handler(std::atomic<bool>& signal_flag, int signal) {
switch (signal) {
case SIGTERM:
WARN("SIGTERM received");
signal_flag.store(true);
break;
case SIGINT:
WARN("SIGINT received");
signal_flag.store(true);
break;
default:
throw (std::runtime_error("Unhandled signal received"));
}
}
auto my_handler = std::bind(terminate_or_interrupt_handler, std::ref(my_class_signal_flag), std::placeholders::_1);
signal(SIGTERM, &my_handler);
Run Code Online (Sandbox Code Playgroud)
但是,我收到此编译错误:
error: cannot …Run Code Online (Sandbox Code Playgroud) #include <iostream>
#include <functional>
using callback = std::function<void(int, void*)>;
void AddCallback(callback cb) {}
void foo(int i) {}
int main() {
auto f = std::bind(&foo, std::placeholders::_1);
AddCallback(f);
}
Run Code Online (Sandbox Code Playgroud)
我用 g++ 9.3.0 和 clang++ 10.0.0 尝试了代码,它们都编译结束没有错误。
绑定结果和回调的类型是否相同?一个是std::function<void(int, void*)>,另一个是等于std::function<void(int)>什么?为什么我可以AddCallback()用不同的类型调用?
这是我的代码片段:
class Base {
public:
Base() {
foo();
bind();
}
virtual void foo() {
std::cout << "base foo\n";
}
void bind() {
fn = std::bind(&Base::foo, this);
};
std::function<void()> fn;
};
class Derived : public Base {
public:
void foo() override {
std::cout << "derived foo\n";
}
void bind() {
}
int val;
};
int main() {
Base* p = new Derived();
p->fn();
}
Run Code Online (Sandbox Code Playgroud)
输出是:
class Base {
public:
Base() {
foo();
bind();
}
virtual void foo() {
std::cout << "base …Run Code Online (Sandbox Code Playgroud) c++ ×10
stdbind ×10
c++11 ×6
std-function ×3
lambda ×2
constructor ×1
mem-fun ×1
overloading ×1
signals ×1
tr1 ×1