如何编写type trait或concept检测类是否存在适配指定类型结构化绑定的方法
实现方案
可以实现该编译期检测能力,以下是不同C++标准下的实现方案:
C++20 Concept 版本(最通用简洁)
该版本可以同时覆盖tuple-like类型(std::tuple、std::pair、自定义tuple协议类型)和普通聚合结构体的结构化绑定场景:
#include <concepts> #include <utility> template <typename Q> concept has_bindable_method = requires(Q q) { // 首先检测Q有无参method成员可调用 q.method(); // 检测method返回值可结构化绑定为2个元素,且类型匹配float、bool [](auto&& res) requires requires { auto [x1, x2] = res; requires std::same_as<decltype(x1), float>; requires std::same_as<decltype(x2), bool>; }(q.method()); };
使用方式:直接用has_bindable_method<Q>作为编译期bool常量即可,比如static_assert(has_bindable_method<Q>);。
如果需要允许隐式类型转换(比如返回int自动转float的场景),把std::same_as替换为std::convertible_to即可。
C++17 SFINAE Type Trait 版本
如果使用C++17及更早标准,可以用SFINAE实现type trait,该版本仅支持tuple-like类型的结构化绑定检测:
#include <type_traits> #include <tuple> #include <utility> template <typename, typename = void> struct has_bindable_method : std::false_type {}; template <typename Q> struct has_bindable_method<Q, std::void_t< decltype(std::declval<Q>().method()), typename std::tuple_size<decltype(std::declval<Q>().method())>::type, typename std::tuple_element<0, decltype(std::declval<Q>().method())>::type, typename std::tuple_element<1, decltype(std::declval<Q>().method())>::type >> : std::bool_constant< std::tuple_size_v<decltype(std::declval<Q>().method())> == 2 && std::is_same_v<std::tuple_element_t<0, decltype(std::declval<Q>().method())>, float> && std::is_same_v<std::tuple_element_t<1, decltype(std::declval<Q>().method())>, bool> > {}; // 辅助常量模板,直接调用即可 template <typename Q> constexpr bool has_bindable_method_v = has_bindable_method<Q>::value;
使用方式:has_bindable_method_v<Q>即为所需的编译期bool常量。
内容的提问来源于stack exchange,提问作者Aisec Nory
相关产品推荐
相关产品推荐

