我有一个带有可变数量参数的成员函数,存储在a中std::function,我希望绑定实例并获得一个独立的函数对象.
template <class T, class R, class... Args>
void connect(const T& t, std::function<R(const T&, Args...)> f) {
std::function<R(Args...)> = /* bind the instance c into the function? */
}
// ...
Class c;
connect(c, &Class::foo);
Run Code Online (Sandbox Code Playgroud)
对于我使用的固定数量的参数std::bind,但我不知道如何为可变参数执行此操作.
与函数指针相比,std :: function的表示法非常好.但是,除此之外,我找不到一个用指针无法替换的用例.那么它只是函数指针的语法糖吗?
在下面的代码中,编译器以静默方式将return-by-copy函数指针强制转换为const-by-const-reference std :: function.调用std :: function实例时,将返回对副本的引用,并且应用程序崩溃(大多数情况下;).
通过比较的方式,普通函数指针不允许这种隐式转换,所以我想知道我是否应该向编译器供应商抱怨(在这种情况下是gcc 4.8),还是这个行为是由标准规定的?
#include <iostream>
#include <functional>
typedef std::function<const std::string&(const std::string& x)> F;
std::string bad(const std::string& x) { return x; }
const std::string& good(const std::string& x) { return x; }
typedef const std::string& (*FP)(const std::string&);
int main(int, char**) {
std::cout << F(&good)("hello") << std::endl;
std::cout << F(&bad)("hello") << std::endl;
FP a = &good;
// FP b = &bad; Not allowed!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
PS这是现实世界问题的简化版本,其中bad实际上是一个lambda返回某种类型的成员:
typedef std::function<const std::string&(const X& x)> F;
F f = …Run Code Online (Sandbox Code Playgroud) 我要问这个的原因是我需要存储std::function在一个向量中,而我们公司内部的向量基本上是在需要更多内存的情况下进行realloc.(基本上memcpy,没有复制/移动操作员参与)
这意味着我们可以放入容器中的所有元素都需要可以轻松复制.
这里有一些代码来演示我有问题的副本:
void* func1Buffer = malloc(sizeof(std::function<void(int)>));
std::function<void(int)>* func1p = new (func1Buffer) std::function<void(int)>();
std::function<void(int)>* func2p = nullptr;
*func1p = [](int) {};
char func2Buffer[sizeof(*func1p)];
memcpy(&func2Buffer, func1p, sizeof(*func1p));
func2p = (std::function<void(int)>*)(func2Buffer);
// func2p is still valid here
(*func2p)(10);
free(func1Buffer);
// func2p is now invalid, even without std::function<void(int)> desctructor get triggered
(*func2p)(10);
Run Code Online (Sandbox Code Playgroud)
我知道我们应该支持元素的复制/移动以便std::function安全存储.但我仍然很好奇std::function上面无效复制的直接原因是什么.
-------------------------------------------------- --UpdateLine ----------------------------------------------- -----
更新了代码示例.
通过调试我们的内部向量,我找到了这种失败的直接原因.
平凡的复制std::function有一些依赖于原始对象的内存,删除原始内存将垃圾严重复制std::function甚至没有原始对象的破坏.
感谢大家对这篇文章的回答.这都是有价值的投入.:)
图书馆代码:
class Resource
{
public:
typedef void (*func_sig)(int, char, double, void*);
//Registration
registerCallback(void* app_obj, func_sig func)
{
_app_obj = app_obj;
_func = func;
}
//Calling when the time comes
void call_app_code()
{
_func(231,'a',432.4234,app_obj);
}
//Other useful methods
private:
void* app_obj;
func_sig _func;
//Other members
};
Run Code Online (Sandbox Code Playgroud)
申请代码:
class App
{
public:
void callme(int, char, double);
//other functions, members;
};
void callHelper(int i, char c, double d, void* app_obj)
{
static_cast<App*>(app_obj)->callme(i,c,d);
}
int main()
{
App a;
Resource r;
r.registercallback(&a, callHelper);
//Do …Run Code Online (Sandbox Code Playgroud) 如何std::function使用函数参数创建一个可变参数模板函数,该函数参数接受可变数量的参数?我试图将问题减少到MWE:
#include <functional>
template <class T> void run(std::function<void(T *)> fun, T *obj) { fun(obj); }
template <class T, class... Args>
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args... args) {
fun(obj, args...);
}
struct Foo {
void bar() {}
};
int main() {
Foo foo;
std::function<void(Foo *)> fun = &Foo::bar;
run(fun, &foo); // works
run<Foo>(&Foo::bar, &foo); // works
run_variadic(fun, &foo); // works
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
}
Run Code Online (Sandbox Code Playgroud)
看起来仅仅存在可变参数模板参数run_variadic使得无法使用成员函数指针直接调用它.clang的错误信息如下:
main.cpp:21:3: error: no matching …Run Code Online (Sandbox Code Playgroud) 这是明确定义的行为吗?
#include <functional>
void foo() {
auto f = new std::function<void()>;
*f = [f]() { delete f; };
(*f)();
f = nullptr;
}
int main() {
foo();
}
Run Code Online (Sandbox Code Playgroud)
使用最新的g ++,如果我在模板中执行此操作,它会在valgrind下运行时导致无效读取,否则它可以正常工作.为什么?这是g ++中的错误吗?
#include <functional>
template<std::size_t>
void foo() {
auto f = new std::function<void()>;
*f = [f]() { delete f; };
(*f)();
f = nullptr;
}
int main() {
foo<0>();
}
Run Code Online (Sandbox Code Playgroud) 鉴于lambda的类型是可确定的(可强制转换为std::function(如果我错了,请纠正我)),重载的函数应该同时使用两个函子。已定义?([&]() -> Type {})
请注意,对于我当前的解决方案,我需要按引用捕获,这就是为什么代码包含其逻辑的原因。
以下示例描述了该问题:
#include <iostream>
#include <string>
#include <functional>
void do_some(std::function<void(int)> thing)
{
thing(5);
}
void do_some(std::function<bool(int)> thing)
{
if (thing(10))
{
std::cout << "it's true!" << std::endl;
}
}
int main()
{
int local_to_be_modified = 0;
do_some(
[&](int in)
{
local_to_be_modified = in;
std::cout << "This is void-" << std::endl;
}
);
do_some(
[&](int in) -> bool
{
// error: call to 'do_some' is ambiguous
local_to_be_modified += in;
std::cout << "This is …Run Code Online (Sandbox Code Playgroud) 假设我有一个像这样的可调用类型:
struct mutable_callable
{
int my_mutable = 0;
int operator()() { // Not const
return my_mutable++;
}
};
Run Code Online (Sandbox Code Playgroud)
请注意,mutable_callable具有operator()修改成员变量的非常量.....
现在假设我创建了一个std::function我的类型:
std::function<int()> foo = mutable_callable{};
Run Code Online (Sandbox Code Playgroud)
现在我可以这样做:
void invoke(std::function<int()> const& z)
{
z();
}
int main()
{
invoke(foo); // foo changed.....oops
}
Run Code Online (Sandbox Code Playgroud)
现在据我所知std::functionsoperator()是const按照:https :
//en.cppreference.com/w/cpp/utility/functional/function/operator()
所以我的直觉是你不应该这样做......
但随后查看:https : //en.cppreference.com/w/cpp/utility/functional/function/function
这似乎没有对可调用类型是否具有常量施加任何限制operator()......
所以我的问题是这样的:我正确地假设这std::function<int()> const&本质上是一样的,std::function<int()>&因为两者的行为实际上没有区别......如果是这样,为什么不const正确?
I'm playing around with callback functions and wish to register multiple functions via std::bind that differ in signatures (altough they all return void). Assigning the result of the std::bind to the std::variant yields in a "conversion to non-scalar type" error. Is it an ambiguity error? Can I provide the compiler with more information?
Dropping the std::bind (which allows the assignment) is not an option as I wish to register the callbacks using some
template <typename Function, typename... Args>
void …Run Code Online (Sandbox Code Playgroud)