如何在 C++ 中的变量中存储任何类型的函数?
How to store any kind of function in a variable in C++?
我将如何在变量中存储具有任意数量参数的任意类型的函数?
像这样:
int add(int i, int j) {
return i + j;
}
template<typename Function, typename... Args>
class Class {
private:
std::function<Function(Args...)> function;
public:
Class(Function _function, Args... _args) {
Now what?
}
};
int main() {
Class test(add, 1, 2);
test.function();
}
你可以尝试类似的东西
#include <iostream>
#include <functional>
#include <tuple>
int add(int i, int j) {
return i + j;
}
template<typename Function, typename... Args>
class Class {
private:
Function function_;
std::tuple<Args...> args;
public:
Class(Function _function, Args... _args) :
function_ { std::forward<Function>(_function) } ,
args{std::forward<Args>(_args)...}
{}
auto function()
{
return std::apply(function_,args);
}
};
int main() {
Class test(add, 1, 2);
std::cout<< test.function() << std::endl ;
}
这就是 bind
的用途!
您的 Class
实际上只是 std::bind
。假设您对它有进一步的用途,并让它包装 std::bind
逻辑。所以我们需要存储一个不接受进一步参数的 std::function
和 returns(在这种情况下)int
…但我们将使其成为通用的(ReturnType
)。
然后在初始化期间你 "bind" 你构造 Class
的参数,并将它们转发到 std::function
(使用 std::forward
允许更多的移动语义复杂参数类型)。
#include <functional>
#include <iostream>
int add(int i, int j)
{
return i + j;
}
template <typename Function, typename... Args>
class Class
{
private:
using ReturnType = std::invoke_result_t<Function, Args...>;
std::function<ReturnType()> function;
public:
Class(Function _function, Args... _args)
: function(std::bind(_function, std::forward<Args>(_args)...))
{}
auto Call()
{
return function();
}
};
int main() {
Class test(add, 1, 2);
std::cout << test.Call() << '\n';
}
// Output: 3
(live demo)
或者,如果您不需要 Class
做更多的事情,那就是:
#include <functional>
#include <iostream>
int add(int i, int j)
{
return i + j;
}
int main()
{
auto func = std::bind(add, 1, 2);
std::cout << func() << '\n';
}
// Output: 3
(live demo)
引导说明
你的 std::function<Function(Args...)>
类型是错误的,因为 Function
是整个函数的类型,但你已经像 return 类型一样使用它了。
在 c++11 及更高版本中,您可以使用 Lambda closures.They 完全按照您的描述进行操作。
例如:
int a = 1;
int b = 2;
int c = [a, b]{ return a + b; }
等于:
struct TestFunctor {
int a;
int b;
TestFunctor(int a, int b):a(a), b(b){}
int operator()(){return a+b;}
};
int a = 1;
int b = 2;
int c = TestFunctor(a,b)();
printf("%d\n", c);
Lambda 可以转换为 std::function 并随时调用...
例如:https://wandbox.org/permlink/1RQUF3UUrsgRdJ42
template<class R>
struct Class {
std::function<R()> function;
template<class F, class...Args>
Class( F&& f, Args&&...args ):
function(
[
f=std::forward<F>(f),
tup=std::make_tuple( std::forward<Args>(args)... )
]
()->R
{
return std::apply(f,tup);
}
)
{} // ctor body
};
template<class F, class...Args>
Class( F, Args... )-> Class< std::invoke_result_t< F const&, Args const&... > >;
那里。
int main() {
Class test(add, 1, 2);
test.function();
}
请注意,我的 Class
类型仅取决于 return 类型。
接受的答案不好,因为 std::bind
完全可以用 lambda 代替,使用 std::bind
在现代 c++ 中是 old-fashioned 并且可能会导致一些性能问题,因为 std::function
的结构有点重。
[请参阅 为什么在 C++14 中使用 std::bind 而不是 lambda?
]
先介绍一下c++20 std::bind_front
,这个函数意在替代std::bind
:
int add(int i, int j, int k) {
return i + j + k;
}
auto f1 = std::bind_front(add, 1);
auto f2 = std::bind_front(add, 1, 2);
auto f3 = std::bind_front(add, 1, 2, 3);
// all will print '6'
std::cout << f1(2, 3) << '\n';
std::cout << f2(3) << '\n';
std::cout << f3() << '\n';
并且不要忘记包含 <functional>
header :)
我将如何在变量中存储具有任意数量参数的任意类型的函数? 像这样:
int add(int i, int j) {
return i + j;
}
template<typename Function, typename... Args>
class Class {
private:
std::function<Function(Args...)> function;
public:
Class(Function _function, Args... _args) {
Now what?
}
};
int main() {
Class test(add, 1, 2);
test.function();
}
你可以尝试类似的东西
#include <iostream>
#include <functional>
#include <tuple>
int add(int i, int j) {
return i + j;
}
template<typename Function, typename... Args>
class Class {
private:
Function function_;
std::tuple<Args...> args;
public:
Class(Function _function, Args... _args) :
function_ { std::forward<Function>(_function) } ,
args{std::forward<Args>(_args)...}
{}
auto function()
{
return std::apply(function_,args);
}
};
int main() {
Class test(add, 1, 2);
std::cout<< test.function() << std::endl ;
}
这就是 bind
的用途!
您的 Class
实际上只是 std::bind
。假设您对它有进一步的用途,并让它包装 std::bind
逻辑。所以我们需要存储一个不接受进一步参数的 std::function
和 returns(在这种情况下)int
…但我们将使其成为通用的(ReturnType
)。
然后在初始化期间你 "bind" 你构造 Class
的参数,并将它们转发到 std::function
(使用 std::forward
允许更多的移动语义复杂参数类型)。
#include <functional>
#include <iostream>
int add(int i, int j)
{
return i + j;
}
template <typename Function, typename... Args>
class Class
{
private:
using ReturnType = std::invoke_result_t<Function, Args...>;
std::function<ReturnType()> function;
public:
Class(Function _function, Args... _args)
: function(std::bind(_function, std::forward<Args>(_args)...))
{}
auto Call()
{
return function();
}
};
int main() {
Class test(add, 1, 2);
std::cout << test.Call() << '\n';
}
// Output: 3
(live demo)
或者,如果您不需要 Class
做更多的事情,那就是:
#include <functional>
#include <iostream>
int add(int i, int j)
{
return i + j;
}
int main()
{
auto func = std::bind(add, 1, 2);
std::cout << func() << '\n';
}
// Output: 3
(live demo)
引导说明
你的 std::function<Function(Args...)>
类型是错误的,因为 Function
是整个函数的类型,但你已经像 return 类型一样使用它了。
在 c++11 及更高版本中,您可以使用 Lambda closures.They 完全按照您的描述进行操作。
例如:
int a = 1;
int b = 2;
int c = [a, b]{ return a + b; }
等于:
struct TestFunctor {
int a;
int b;
TestFunctor(int a, int b):a(a), b(b){}
int operator()(){return a+b;}
};
int a = 1;
int b = 2;
int c = TestFunctor(a,b)();
printf("%d\n", c);
Lambda 可以转换为 std::function 并随时调用... 例如:https://wandbox.org/permlink/1RQUF3UUrsgRdJ42
template<class R>
struct Class {
std::function<R()> function;
template<class F, class...Args>
Class( F&& f, Args&&...args ):
function(
[
f=std::forward<F>(f),
tup=std::make_tuple( std::forward<Args>(args)... )
]
()->R
{
return std::apply(f,tup);
}
)
{} // ctor body
};
template<class F, class...Args>
Class( F, Args... )-> Class< std::invoke_result_t< F const&, Args const&... > >;
那里。
int main() {
Class test(add, 1, 2);
test.function();
}
请注意,我的 Class
类型仅取决于 return 类型。
接受的答案不好,因为 std::bind
完全可以用 lambda 代替,使用 std::bind
在现代 c++ 中是 old-fashioned 并且可能会导致一些性能问题,因为 std::function
的结构有点重。
[请参阅 为什么在 C++14 中使用 std::bind 而不是 lambda? ]
先介绍一下c++20 std::bind_front
,这个函数意在替代std::bind
:
int add(int i, int j, int k) {
return i + j + k;
}
auto f1 = std::bind_front(add, 1);
auto f2 = std::bind_front(add, 1, 2);
auto f3 = std::bind_front(add, 1, 2, 3);
// all will print '6'
std::cout << f1(2, 3) << '\n';
std::cout << f2(3) << '\n';
std::cout << f3() << '\n';
并且不要忘记包含 <functional>
header :)