如何检测元组类型重复场景下的重载决议失败并触发static_assert?
如何在tuple类型索引查找中捕获重复类型的错误?
以下代码实现了元函数tuple_index,用于获取std::tuple中目标类型对应的索引:
#include <tuple> #include <type_traits> #include <utility> #include <cstddef> template <typename ...> struct always_false : std::false_type {}; template <> struct always_false<decltype([] {})> : std::true_type {}; template <typename ...Ts> inline constexpr bool always_false_v = always_false<Ts...>::value; template <typename> struct type_wrapper {}; template <std::size_t I, typename T> struct tuple_index_impl_base { auto foo(type_wrapper<T>) -> std::integral_constant<std::size_t, I>; }; template <typename ...Ts> struct tuple_index_impl_base_fallback { auto foo(...) { static_assert(always_false_v<Ts...>, "Type not exist."); } }; template <typename, typename ...> struct tuple_index_impl; template <std::size_t ...Is, typename ...Ts> struct tuple_index_impl<std::index_sequence<Is...>, Ts...> : tuple_index_impl_base<Is, Ts>..., tuple_index_impl_base_fallback<Ts...> { using tuple_index_impl_base<Is, Ts>::foo...; using tuple_index_impl_base_fallback<Ts...>::foo; }; template <typename, typename> struct tuple_index; template <typename T, typename ...Ts> struct tuple_index<T, std::tuple<Ts...>> : decltype(std::declval<tuple_index_impl<std::make_index_sequence<std::tuple_size_v<std::tuple<Ts...>>>, Ts...>>().foo(std::declval<type_wrapper<T>>())) {}; template <typename T, typename U> inline constexpr std::size_t tuple_index_v = tuple_index<T, U>::value;
不同场景的表现
类型唯一存在时:代码可正常返回索引
constexpr std::size_t i = tuple_index_v<char&, std::tuple<int, float, char, char&, const char*, char>>; // i == 3类型不存在时:触发
static_assert输出友好错误constexpr std::size_t i = tuple_index_v<long, std::tuple<int, float, char, char&, const char*, char>>; // 错误 C2338: static_assert failed: 'Type not exist.'类型重复存在时:编译器抛出重载歧义错误,而非预设的友好提示
constexpr std::size_t i = tuple_index_v<char, std::tuple<int, float, char, char&, const char*, char>>; // 错误 C2668: 'tuple_index_impl_base_fallback<int,float,char,char &,const char *,char>::foo': 对重载函数的调用不明确
当重载集合中存在多个匹配的foo函数时,编译器不会选择回退的foo(...)重载。如何在这种场景下检测重载决议失败,并通过static_assert输出友好的错误信息?
内容的提问来源于stack exchange,提问作者El Mismo Sol
相关产品推荐
相关产品推荐

