如何编写C++ requires表达式检测特定成员/静态函数及参数类型
如何用C++ requires表达式检测类的特定成员函数、静态函数(含参数类型要求)
我来帮你搞定这个C++ concept的问题,你已经写好了静态函数StaticDescription和无参成员函数Description的检测逻辑,现在只需要补全Greet方法的检测就可以了。
先回顾下你已有的正确写法:
- 检测静态成员函数:直接用
T::StaticDescription()调用,通过-> std::same_as<std::string>约束返回值类型,不需要类实例,这部分完全没问题。 - 检测无参非静态成员函数:用requires参数里的
t(类实例)调用Description(),同样约束返回值类型,也很正确。
检测带参数的成员函数Greet
对于带参数的成员函数,我们需要在requires表达式里传递一个符合参数类型的“模拟值”,不需要实际创建对象,编译期就能完成检查。这里有两种常用写法:
写法1:在requires参数列表里声明参数变量
这种方式更直观易读,直接在requires的参数列表里加一个std::string_view类型的变量,用它来调用Greet:
#include <string> #include <string_view> #include <format> #include <concepts> struct ConcretePrintable { static std::string StaticDescription() { return "static description"; } std::string Description() { return "description"; } std::string Greet(std::string_view name) { return std::format("Hi, {}!", name); } }; template <typename T> concept Printable = requires(T t, std::string_view sv) { // 检测静态成员函数StaticDescription,返回值为std::string { T::StaticDescription() } -> std::same_as<std::string>; // 检测非静态成员函数Description,返回值为std::string { t.Description() } -> std::same_as<std::string>; // 检测Greet:接受std::string_view参数,返回值为std::string { t.Greet(sv) } -> std::same_as<std::string>; };
写法2:用std::declval生成模拟参数
如果不想在requires参数列表里加额外变量,可以用std::declval(需要包含<utility>头文件),它能在编译期生成指定类型的右值引用,用来模拟参数传递:
#include <string> #include <string_view> #include <format> #include <concepts> #include <utility> // 引入std::declval struct ConcretePrintable { static std::string StaticDescription() { return "static description"; } std::string Description() { return "description"; } std::string Greet(std::string_view name) { return std::format("Hi, {}!", name); } }; template <typename T> concept Printable = requires(T t) { { T::StaticDescription() } -> std::same_as<std::string>; { t.Description() } -> std::same_as<std::string>; // 用std::declval生成std::string_view类型的模拟参数 { t.Greet(std::declval<std::string_view>()) } -> std::same_as<std::string>; };
补充说明
- 两种写法都能完成检测,选择哪种取决于你的代码可读性需求:写法1更直白,写法2适合参数类型复杂或不想扩展requires参数列表的场景。
- 如果
Greet的参数是左值引用(比如const std::string_view&),只需要把std::declval的模板参数改成const std::string_view&即可,或者在写法1里用const std::string_view& sv。 - 这些检测都是编译期完成的,不会产生运行时开销,完全符合concept的设计初衷。
内容的提问来源于stack exchange,提问作者citelao
相关产品推荐
相关产品推荐

