如何声明返回std::optional<满足event concept类型>的std::function?
如何声明返回std::optional<满足event concept类型>的std::function
你的两种写法都存在概念误解:
- 第一种写法里,
event是concept(概念),不是具体类型,不能直接作为std::optional的模板参数,所以编译器报错“Too few template arguments for concept 'event'”。 - 第二种写法里,
event<t>是一个布尔约束检查(用来判断t是否满足event概念),不是合法的类型,因此编译器提示“Template argument for template type parameter must be a type”。
下面提供两种可行的实现方案,对应不同的使用场景:
方案1:针对特定满足event的类型定义std::function
如果你的场景中,明确知道要使用的具体event类型,可以用带concept约束的模板别名,为每个满足event的类型生成对应的std::function类型:
#include <functional> #include <optional> #include <concepts> template <typename T> concept event = requires(T p_t) { { T::id } -> std::same_as<const size_t&>; requires std::default_initializable<T>; }; // 模板别名:仅当T满足event概念时,才会生成对应的std::function类型 template <event T> using EventFunc = std::function<std::optional<T>(int)>; // 示例:满足event概念的自定义类型 struct LoginEvent { static constexpr const size_t& id = [](){ static size_t val = 1001; return val; }(); LoginEvent() = default; }; int main() { // 使用具体的event类型实例化EventFunc EventFunc<LoginEvent> handleLogin = [](int userId) -> std::optional<LoginEvent> { if (userId > 0) { return LoginEvent{}; } return std::nullopt; }; }
方案2:容纳任意满足event的函数(类型擦除)
如果需要一个能存储任意返回满足event的std::optional的函数的类型,std::function无法直接做到(因为它要求固定的返回类型签名),这时可以通过类型擦除实现一个包装类:
#include <functional> #include <optional> #include <concepts> #include <memory> #include <any> template <typename T> concept event = requires(T p_t) { { T::id } -> std::same_as<const size_t&>; requires std::default_initializable<T>; }; class AnyEventFunction { public: // 构造函数:接受任意满足event的函数类型 template <event T> AnyEventFunction(std::function<std::optional<T>(int)> func) : impl_(std::make_unique<Impl<T>>(std::move(func))) {} // 调用函数:返回std::any存储结果,需要手动转换回具体类型 std::any operator()(int arg) const { return impl_->invoke(arg); } private: // 类型擦除的基类 struct ImplBase { virtual ~ImplBase() = default; virtual std::any invoke(int) const = 0; }; // 模板子类:包装具体的event函数 template <event T> struct Impl : ImplBase { std::function<std::optional<T>(int)> func_; Impl(std::function<std::optional<T>(int)> func) : func_(std::move(func)) {} std::any invoke(int arg) const override { return func_(arg); } }; std::unique_ptr<ImplBase> impl_; }; // 示例:两个不同的event类型 struct PayEvent { static constexpr const size_t& id = [](){ static size_t val = 2001; return val; }(); PayEvent() = default; }; struct LogoutEvent { static constexpr const size_t& id = [](){ static size_t val = 3001; return val; }(); LogoutEvent() = default; }; int main() { AnyEventFunction handlePay = [](int amount) -> std::optional<PayEvent> { return amount > 0 ? PayEvent{} : std::nullopt; }; AnyEventFunction handleLogout = [](int) -> std::optional<LogoutEvent> { return LogoutEvent{}; }; // 使用时需要将std::any转换回具体的optional类型 auto payResult = std::any_cast<std::optional<PayEvent>>(handlePay(100)); auto logoutResult = std::any_cast<std::optional<LogoutEvent>>(handleLogout(0)); }
内容的提问来源于stack exchange,提问作者canellas
相关产品推荐
相关产品推荐

