英文:
How to construct no-op callback from std::function signature in C++?
问题
我有一些回调定义,例如:
using TSomeCallback = std::function<ReturnType(Type1, Type2, Type3, …)>;
我还有一些接受此回调作为参数的方法:
void SetCallback(TSomeCallback);
我想要定义一个模板,可以直接从 TSomeCallback
实例化一个无操作回调:
void SetCallback(TSomeCallback = GetNoopCallback<TSomeCallback>()); // 或者
void SetCallback(TSomeCallback = GetNoopCallback(TSomeCallback())); // 或者任何其他方式。
我找到了这个答案 - 它很好,但我不知道如何根据我的需求进行改进。
英文:
I have some callback definition like:
using TSomeCallback = std::function<ReturnType(Type1, Type2, Type3, …)>;
Also I have some method that accepts this callback as an argument:
void SetCallback(TSomeCallback);
All I want is to define some template that instantiates no-op callback directly from TSomeCallback:
void SetCallback(TSomeCallback = GetNoopCallback<TSomeCallback>()); // or
void SetCallback(TSomeCallback = GetNoopCallback(TSomeCallback())); // or any other way.
I found this answer - it's good, but I don't know how to improve it for my purpose.
答案1
得分: 4
你可以这样做:
void SetCallback(TSomeCallback = [](auto...){});
但我更推荐这样做:
void SetCallback(TSomeCallback = {})
然后在内部检查回调是否非空。或者也许可以不提供默认参数,如果你不想被回调的话就不调用 SetCallback
!
英文:
You can do it this way
void SetCallback(TSomeCallback = [](auto...){});
but I would recommend rather
void SetCallback(TSomeCallback = {})
and check for the callback being non-empty inside. Or perhaps don't supply a default parameter and just don't call SetCallback
if you don't want to be called back!
答案2
得分: 3
你可以使用 lambda 表达式来构造一个不执行任何操作的 std::function< ... >
。只要返回类型是 void
,那么这个方法可以工作:
#include <functional>
#include <string>
using namespace std;
using TSomeCallback = std::function<void(int, double, int)>;
int main() {
TSomeCallback tc = [](auto...) {};
tc(42, 12.0, 42);
}
英文:
You can use a lambda to construct a std::function< ... >
that does nothing. Provided, the return type is void
then this works:
#include <functional>
#include <string>
using namespace std;
using TSomeCallback = std::function<void(int,double,int)>;
int main() {
TSomeCallback tc = [](auto...){};
tc(42,12.0,42);
}
答案3
得分: 2
你可以为返回 void
的函数实现 GetNoopCallback
,像这样:
template <class F>
F GetNoopCallback() {
return [](auto&&...){};
}
然后:
void SetCallback(TSomeCallback = GetNoopCallback<TSomeCallback>());
英文:
You can implement GetNoopCallback
for void
-returning functions like this:
template <class F>
F GetNoopCallback() {
return [](auto&&...){};
}
Then:
void SetCallback(TSomeCallback = GetNoopCallback<TSomeCallback>());
答案4
得分: 1
#include <type_traits>
template <typename result>
requires (std::is_void_v<result> ||
std::is_default_constructible_v<result>)
constexpr auto return_default = [](auto&& ...)
noexcept (std::is_void_v<result> ||
std::is_nothrow_default_constructible_v<result>)
{
if constexpr (std::is_void_v<result>)
return;
else
return result {};
};
std::function<void(int)> f1 = return_default<void>;
auto f2 = std::function<A(B,C)>{return_default<A>};
struct any_function_default{
template<typename result, typename ... args>
requires (std::is_void_v<result> ||
std::is_default_constructible_v<result>)
constexpr operator std::function<result(args ...)> () const {
return [] (auto&& ...) {
if constexpr (std::is_void_v<result>)
return;
else
return result {};
};
};
};
std::function<void(int)> f1 = any_function_default{};
auto f2 = std::function<A(B,C)>{any_function_default{}};
This is the translation of the provided code without the code comments and explanations.
<details>
<summary>英文:</summary>
```C++
#include <type_traits>
template <typename result>
requires (std::is_void_v<result> ||
std::is_default_costructible_v<result>)
constexpr auto return_default = [] (auto&& ...)
noexcept (std::is_void_v<result> ||
std::is_nothrow_default_costructible_v<result>)
{
if constexpr (std::is_void_v<result>)
return;
else
return result {};
};
Now just cast or use the template variable as rvalue:
std::function<void(int)> f1 = return_default<void>;
auto f2 = std::function<A(B,C)>{return_default<A>};
You can take one step further to remove the need for a return type:
struct any_function_default{
template<typename result, typname ... args>
requires (std::is_void_v<result> ||
std::is_default_costructible_v<result>)
constexpr operator std::function<result(args ...)> () const {
return [] (auto&& ...) {
if constexpr (std::is_void_v<result>)
return;
else
return result {};
};
};
};
Now use any_function_default
as the universal default for functions:
std::function<void(int)> f1 = any_function_default{};
auto f2 = std::function<A(B,C)> { any_function_default{} };
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论