我应该如何使用默认参数定义 std::function 变量
How should I define a std::function variable with default arguments?
要将 std::function 变量设置为具有默认参数的 lambda 函数,我可以使用auto
如下所示:
auto foo = [](int x = 10){cout << x << endl;};
foo();
这将打印 10。
但是我希望 foo 变量驻留在结构中。在结构中我不能使用auto
.
struct Bar
{
auto foo = [](int x = 10}(cout << x << endl}; //error: non-static data member declared ‘auto’
};
Bar bar;
bar.foo();
将auto
替换为 std::function
struct Bar
{
std::function<void(int x = 10)> foo = [](int x = 10}(cout << x << endl}; //error: default arguments are only permitted for function parameters
};
Bar bar;
bar.foo();
或
struct Bar
{
std::function<void(int)> foo = [](int x = 10}(cout << x << endl};
};
Bar bar;
bar.foo(); //error: no match for call to ‘(std::function<void(int)>) ()’
没有结构并替换 std::function 的 auto
:
std::function<void(int x)> foo = [](int x = 10){cout << x << endl;};
foo(); //error: no match for call to ‘(std::function<void(int)>) ()’
那么我应该如何声明 foo?
std::function
中的签名基于您计划如何调用它,而不是基于您如何构造/分配它。 由于您希望以两种不同的方式调用它,因此您需要存储到不同的std::function
对象,如下所示:
struct Call
{
template<typename F>
explicit Call(F f) : zero_(f), one_(std::move(f)) {}
void operator()() { zero_(); }
void operator()(int i) { one_(i); }
std::function<void()> zero_;
std::function<void(int)> one_;
};
或者,您可以自己执行类型擦除(std::function
幕后执行的操作)以仅存储一次 lambda,如下所示:
class TECall
{
struct Concept
{
Concept() = default;
Concept(Concept const&) = default;
virtual ~Concept() = default;
virtual Concept* clone() const = 0;
virtual void operator()() = 0;
virtual void operator()(int) = 0;
};
template<typename T>
struct Model final : Concept
{
explicit Model(T t) : data(std::move(t)) {}
Model* clone() const override { return new Model(*this); }
void operator()() override { data(); }
void operator()(int i) override { data(i); }
T data;
};
std::unique_ptr<Concept> object;
public:
template<typename F>
TECall(F f) : object(new Model<F>(std::move(f))) {}
TECall(TECall const& that) : object(that.object ? that.object->clone() : nullptr) {}
TECall(TECall&& that) = default;
TECall& operator=(TECall that) { object = std::move(that.object); return *this; }
void operator()() { (*object)(); }
void operator()(int i) { (*object)(i); }
};
解决此问题的一种方法是将std::function
包装在为您实现默认参数的函子对象中:
struct MyFunc
{
void operator()(int x = 10) { f(x); }
std::function<void(int x)> f;
};
struct Bar
{
MyFunc foo = {[](int x){std::cout << x << "n";}};
};
int main() {
Bar bar;
bar.foo();
}
在 C++20 中,您将能够执行以下操作:
struct foo {
decltype([](int a = 10){std::cout << a << 'n';}) my_lambda{};
};
int main() {
foo f;
f.my_lambda();
f.my_lambda(5);
}
住在戈博尔特上
它看起来确实有点奇怪,但它工作得很好。
使这成为可能的是能够在未评估的上下文中使用 lambda,并默认构造无状态 lambda。
不知道这是否会对您有所帮助,但您可以将 lambda 存储在模板化结构中。
template <typename F>
struct Bar {
F foo;
Bar (F fun): foo (std::move (fun)) {}
};
auto f = [](int x = 10) {cout << x << endl;};
Bar<decltype (f)> bar (f);
bar.foo();
auto makeFun = [](){return [](int x = 10) {cout << x << endl;};};
Bar<decltype (makeFun())> bar2 (makeFun());
bar2.foo();
相关文章:
- Confusion: decltype vs std::function
- 为什么 std::function 可以作为 std::not2 的参数?
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 传递给std::function template的template参数究竟代表什么
- 绑定派生类方法C++从实例范围之外的分隔 std::function 变量调用
- 将函数包装器转换为 std::function
- 类型擦除的std::function与虚拟函数调用的开销
- C++ std::function 对于类 exept 的所有实例都是空的(只有 Visual2019 编译器问题)
- 如果模板没有可变参数,则 Lambda 被推导出为 std::function
- 将 lambda 表达式传递给 std::function in C++
- 模板类的部分模板专用化,如 std::function
- 可变参数模板参数扩展 类型为 std::function 的类成员
- 从 std::function in C++ 访问模板化 lambda
- 什么是 std::function::argument_type 的替代品?
- C++派生类重载函数(带有 std::function 参数)不可见
- 如何在 qi 符号表中使用 std::function
- 将 std::function 与模板一起使用
- C++ 事件管理器的回调,使用 std::function 和 std:bind 以及派生类作为参数
- 我需要在 std::function 上使用 unique_ptr 吗?
- 如何将函数指针从 std::function 传递到 Linux 克隆?