能否借助任意C++标准在编译时检测类是否含至少一个公有方法?
C++编译时检测类是否存在至少一个公有方法
可以实现,但根据C++版本的不同,实现方式有所差异:
针对特定签名的公有方法(C++11及以上)
如果只需要检测是否存在特定签名的公有成员函数(比如无参void返回的函数),可以用SFINAE(替换失败并非错误)技巧实现:
#include <type_traits> namespace detail { // 尝试匹配无参void返回的公有成员函数 template <typename T> auto test(int) -> decltype(std::declval<void (T::*)()>(), std::true_type{}); // 兜底重载:匹配失败时返回false template <typename T> std::false_type test(...); } template <typename T> constexpr bool check = decltype(detail::test<T>(0))::value;
这个实现可以满足你给出的示例:
S1有void can(),匹配成功,check<S1>为true;S2无任何成员函数,匹配失败,check<S2>为false;C1的成员函数是私有,无法在外部访问,匹配失败,check<C1>为false;C2有void any_name(),匹配成功,check<C2>为true。
但这个方法的局限性是只能检测特定签名的函数,无法覆盖所有可能的成员函数签名。
通用检测任意公有方法(C++23及以上)
C++23引入了反射特性,可以枚举类的所有成员,从而完美实现通用检测:
#include <reflect> template <typename T> constexpr bool check = []{ // 遍历类的所有成员 for (const auto& member : std::reflect<T>::members()) { // 判断是否是公有成员函数 if (member.is_function() && member.access() == std::reflect_access::public_) { return true; } } return false; }();
这个方法可以检测任意签名的公有成员函数,包括带参数、不同返回值的函数,同时会忽略私有/保护成员函数和非函数成员。
注意事项
- 在C++23之前,没有完美的通用方法可以检测任意签名的公有成员函数,因为无法在编译时枚举类的所有成员;
- 如果你的场景中不需要覆盖所有签名,仅针对特定类型的方法,SFINAE方法足够满足需求。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

