如何用C++20 Concept约束支持指定参数组合的noexcept可调用对象
解决方案:约束可调用对象支持多组noexcept调用
要实现同时约束可调用对象能以<int>和<const char*, const char*>两组参数进行noexcept调用,我们可以通过拆分约束、组合验证的方式完成:
1. 基础Concept:检查单组参数的noexcept调用
先定义一个通用Concept,用于判断可调用对象T能否用指定的Args...参数完成noexcept调用:
template <typename T, typename... Args> concept IsNoExceptCallableWith = requires(T&& f, Args&&... args) { requires noexcept(f(std::forward<Args>(args)...)); };
这里用std::forward保留参数的左值/右值属性,让约束检查更贴合实际调用场景。
2. 组合多组参数的约束
接着定义一个专门的Concept,同时验证两种调用场景的noexcept属性:
template <typename T> concept NoExceptMultiCallable = IsNoExceptCallableWith<T, int> && IsNoExceptCallableWith<T, const char*, const char*>;
只有当可调用对象同时满足两种参数组合的noexcept调用要求时,才会通过该约束。
3. 在模板函数中应用约束
修改foo函数,使用上面的组合约束:
#include <iostream> #include <utility> template <typename T, typename... Args> concept IsNoExceptCallableWith = requires(T&& f, Args&&... args) { requires noexcept(f(std::forward<Args>(args)...)); }; template <typename T> concept NoExceptMultiCallable = IsNoExceptCallableWith<T, int> && IsNoExceptCallableWith<T, const char*, const char*>; template <NoExceptMultiCallable Fn> void foo(Fn f) noexcept { f(1); f("hello", "world"); } int main() { auto lambda = [](auto&& a, auto&&... rest) noexcept { std::cout << a; if constexpr(sizeof...(rest) != 0) { std::cout << (rest << ...); } std::cout << std::endl; }; foo(lambda); // 编译通过:lambda符合两组参数的noexcept调用约束 }
关键细节
- 示例中的lambda需要显式添加
noexcept声明:C++中泛型lambda的调用运算符默认不会自动推导为noexcept,显式声明才能确保满足约束。 - 如果可调用对象在任意一组参数下的调用不满足noexcept,编译器会直接拒绝实例化
foo,达到约束目的。
扩展说明
如果后续需要支持更多参数组合,只需在NoExceptMultiCallable中追加对应的IsNoExceptCallableWith条件即可,例如:
template <typename T> concept NoExceptMultiCallable = IsNoExceptCallableWith<T, int> && IsNoExceptCallableWith<T, const char*, const char*> && IsNoExceptCallableWith<T, double, std::string>;
内容的提问来源于stack exchange,提问作者Leherenn
相关产品推荐
相关产品推荐

