我有许多具有不同签名的回调函数.理想情况下,我想将它们放在一个向量中,并根据某些条件调用适当的一个.
例如
void func1(const std::string& value);
void func2(const std::string& value, int min, int max);
const std::vector<std::function<void(std::string)>> functions
{
func1,
func2,
};
Run Code Online (Sandbox Code Playgroud)
我意识到上述情况是不可能的,但我想知道是否有任何我应该考虑的替代方案.我还没有找到任何东西,我已经尝试过,std::bind但没有成功实现我想要的东西.
这样的事情可能吗?
当移动-构造std::function从一个对象的λ,其中该拉姆达具有由值捕获,看来该物体的移动,构造函数,是值捕获被调用两次。考虑
#include <功能>
#include <iostream>
结构体
{
整数值 = 1;
Foo() = 默认值;
Foo(const Foo &) {}
富(富&&)
{
std::cout << "移动构造函数" << std::endl;
}
};
int main()
{
福福;
自动 lambda = [=]() { 返回 foo.value; };
std::cout << "---------" << std::endl;
std::function<int()> func(std::move(lambda));
std::cout << "---------" << std::endl;
返回0;
}
输出是
---------
move ctor
move ctor
---------
Run Code Online (Sandbox Code Playgroud)
我在 Mac OS X Catalina 上工作,我的编译器是
g++-9 (Homebrew GCC 9.3.0) 9.3.0
Run Code Online (Sandbox Code Playgroud)
我用g++ -std=c++17. …
这可能是一个哲学问题,但我遇到了以下问题:
如果您定义了一个std :: function,并且没有正确初始化它,那么您的应用程序将崩溃,如下所示:
typedef std::function<void(void)> MyFunctionType;
MyFunctionType myFunction;
myFunction();
Run Code Online (Sandbox Code Playgroud)
如果函数作为参数传递,如下所示:
void DoSomething (MyFunctionType myFunction)
{
myFunction();
}
Run Code Online (Sandbox Code Playgroud)
然后,当然,它也崩溃了.这意味着我被迫添加这样的检查代码:
void DoSomething (MyFunctionType myFunction)
{
if (!myFunction) return;
myFunction();
}
Run Code Online (Sandbox Code Playgroud)
需要这些检查让我回到旧的C日,你还必须明确检查所有指针参数:
void DoSomething (Car *car, Person *person)
{
if (!car) return; // In real applications, this would be an assert of course
if (!person) return; // In real applications, this would be an assert of course
...
}
Run Code Online (Sandbox Code Playgroud)
幸运的是,我们可以在C++中使用引用,这阻止我编写这些检查(假设调用者没有将nullptr的内容传递给函数:
void DoSomething (Car &car, Person &person)
{
// I can assume that …Run Code Online (Sandbox Code Playgroud) 考虑这个模板功能:
template<typename ReturnT>
ReturnT foo(const std::function<ReturnT ()>& fun)
{
return fun();
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器不能ReturnT从传递的调用签名中推断出来?
bool bar() { /* ... */ }
foo<bool>(bar); // works
foo(bar); // error: no matching function call
Run Code Online (Sandbox Code Playgroud) 为什么在C++标准中定义std :: function <> :: operator()是:
R operator()(ArgTypes...) const;
Run Code Online (Sandbox Code Playgroud)
并不是
R operator()(ArgTypes&&...) const;
Run Code Online (Sandbox Code Playgroud)
?
有人会认为要正确转发参数,我们需要&&然后std::forward<ArgTypes>...在转发呼叫时在函数体中使用?
我部分重新实现了std :: function来测试这个,我发现如果我使用&&,当我稍后尝试通过值将参数传递给operator()时,我从g ++中得到"无法将'xxx'左值'绑定到'xxx &&'" .我认为我对rvalue/forwarding概念有了足够的把握,但我还是不能理解这一点.我错过了什么?
作为一个懒惰的开发人员,我喜欢使用这个技巧来指定一个默认函数:
template <class Type, unsigned int Size, class Function = std::less<Type> >
void arrange(std::array<Type, Size> &x, Function&& f = Function())
{
std::sort(std::begin(x), std::end(x), f);
}
Run Code Online (Sandbox Code Playgroud)
但是在一个非常特殊的情况下我遇到了一个问题,如下所示:
template <class Type, unsigned int Size, class Function = /*SOMETHING 1*/>
void index(std::array<Type, Size> &x, Function&& f = /*SOMETHING 2*/)
{
for (unsigned int i = 0; i < Size; ++i) {
x[i] = f(i);
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我希望默认函数相当于:( [](const unsigned int i){return i;}一个只返回传递值的函数).
为了做到这一点,我需要写什么而不是/*SOMETHING 1*/和/*SOMETHING 2*/?
我有一个更高阶的函数map,类似于STL for_each,并将一个std::function对象映射vector到一些东西上.
template<class T, class U>
vector<U> map(function<U (T)> f, vector<T> xs) {
vector<U> ret;
for (auto &x: xs)
ret.push_back(f(x));
return ret;
}
Run Code Online (Sandbox Code Playgroud)
现在,我想有这样的高阶功能拍摄的类型两个对象function<int (const vector<T>&)>和 function<int (vector<T>)>,如所附小例子.
问题是,function<int (const vector<T>&)>并且 function<int (vector<T>)>似乎可以相互转换(请参阅head和head2),但map不会采用const引用版本function<int (const vector<int>&)>(请参阅参考资料Q1).
可以map通过显式转换(Q2)来接受const引用版本,但这很麻烦.
我想知道,一般来说,是否可以编写一个deref删除const引用的函数function<int (const vector<T>&)>并返回一个function<int (vector<T>)>?
(如果可以,那么我将不必为const refs编写两个相同的重载/ map实现).
谢谢.
#include <vector>
#include …Run Code Online (Sandbox Code Playgroud) 在C++ 11中,您可以像这样实例化std :: function:
std::function<void(int)> f1;
std::function<int(std::string, std::string)> f2;
//and so on
Run Code Online (Sandbox Code Playgroud)
但是虽然网上有大量关于可变参数模板的信息,但我找不到任何关于如何编写std :: function-like模板的文章,这些模板会接受带括号的参数.任何人都可以解释一下语法及其局限性,或者至少指出现有的解释吗?
我正在学习C++中的函数式编程.我的目的是将非泛型函数作为参数传递.我知道模板方法,但是我想将函数签名限制为API设计的一部分.我在cpp.sh上编写了4个不同的方法示例:
// Example program
#include <iostream>
#include <string>
#include <functional>
typedef int(functor_type)(int);
int by_forwarding(functor_type &&x) {
return x(1);
}
int functor_by_value(functor_type x) {
return x(1);
}
int std_func_by_value(std::function<functor_type> x) {
return x(1);
}
int std_func_by_forwarding(std::function<functor_type> &&x) {
return x(1);
}
int main()
{
std::cout << functor_by_value([](int a){return a;}); // works
std::cout << std_func_by_value([](int a){return a;}); // works
std::cout << std_func_by_forwarding(std::move([](int a){return a;})); // works
//std::cout << by_forwarding([](int a){return a;}); // how to move lambda with forwarding …Run Code Online (Sandbox Code Playgroud) C++23 引入了std::function的表兄弟std::move_only_function,就像它的名字一样,它是仅移动可调用对象的仅移动包装器(演示):
#include <functional>
#include <memory>
int main() {
auto l = [p = std::make_unique<int>(0)] { };
std::function<void(void)> f1{std::move(l)}; // ill-formed
std::move_only_function<void(void)> f2{std::move(l)}; // well-formed
}
Run Code Online (Sandbox Code Playgroud)
但与 不同的是std::function,该标准没有为其定义推导指南(演示):
#include <functional>
int func(double) { return 0; }
int main() {
std::function f1{func}; // guide deduces function<int(double)>
std::move_only_function f2{func}; // deduction failed
}
Run Code Online (Sandbox Code Playgroud)
禁止 CTAD 有理由吗?