如何在C++20中用Concepts声明泛型高阶函数的签名?
解决泛型可调用对象的返回类型约束问题
原代码中std::convertible_to<std::function<int(auto)>>的写法不合法,因为int(auto)不是有效的函数类型声明,auto不能直接用于std::function的模板参数来表示泛型参数。以下是几种可行的解决方式:
1. 自定义Concept直接约束可调用行为
最直观的方式是自定义一个Concept,直接描述返回的可调用对象需要满足的条件:可以接受任意类型的参数,且返回值为int。
#include <concepts> // 定义Concept:可接受任意参数并返回int的可调用对象 template<typename F> concept IntReturningGenericCallable = requires(F f, auto x) { { f(x) } -> std::same_as<int>; }; // 使用自定义Concept约束Foo的返回类型 IntReturningGenericCallable auto Foo() { return [](auto x) { return 1; }; } int main() { return Foo()(1); }
这种方式无需依赖std::function,直接对可调用对象的行为进行约束,同时避免了std::function带来的类型擦除开销,性能更优。
2. 结合std::invocable与返回值约束
也可以利用标准库的std::invocableConcept,搭配返回值的约束来实现:
#include <concepts> template<typename F> concept GenericIntReturner = std::invocable<F, auto> && // 可被任意参数调用 requires(F f, auto x) { { f(x) } -> std::same_as<int>; // 返回值必须是int }; GenericIntReturner auto Foo() { return [](auto x) { return 1; }; } int main() { return Foo()(1); }
3. 使用尾随requires子句约束返回类型
如果不想单独定义Concept,也可以直接在函数声明中用尾随requires子句来约束返回值的行为:
#include <concepts> #include <utility> auto Foo() -> auto requires requires(auto x) { // 检查返回的可调用对象调用任意x后返回int { std::declval<decltype(Foo())>()(x) } -> std::same_as<int>; } { return [](auto x) { return 1; }; } int main() { return Foo()(1); }
这种写法无需额外定义Concept,但可读性稍差,适合简单场景。
内容的提问来源于stack exchange,提问作者bradgonesurfing
相关产品推荐
相关产品推荐

