请考虑以下代码片段:
#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;
它实现一个元函数tuple_index
来获取与std::tuple
中的类型相对应的索引。
如果类型存在并且在元组中只存在一次,则该方法可以正常工作:
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>>; // error C2338: static_assert failed: 'Type not exist.'
(live demo)(英文)
但是,如果该类型存在多次,编译器将开始比较ambiguous call to overloaded function
:
constexpr std::size_t i = tuple_index_v<char, std::tuple<int, float, char, char&, const char*, char>>; // error C2668: 'tuple_index_impl_base_fallback<int,float,char,char &,const char *,char>::foo': ambiguous call to overloaded function
(live demo)
如果重载集中有两个相同的函数,编译器似乎不会选择回退函数(在本例中为tuple_index_impl_base_fallback<Ts...>::foo(...)
)。
如何在这种情况下检测过载解析失败并使用static_assert
捕获它?
1条答案
按热度按时间gr8qqesn1#
您可以使用
requires
运算式检查多载解析是否会成功: