这实际上很容易用模板类型特征来解决:
#include <type_traits> // std::integral_constant
#include <cstddef> // std::size_t
// Recursive base template (specialized below)
template <std::size_t Current, typename T, typename...Types>
struct find_type_aux;
// Specialization: If we find a match
template <std::size_t Current, typename T, typename...Types>
struct find_type_aux<Current,T,T,Types...>
: std::integral_constant<std::size_t,Current>
{};
// Specialization: If we haven't found a match, but still have some left in the pack
template <std::size_t Current, typename T, typename Type0, typename...Types>
struct find_type_aux<Current,T,Type0, Types...>
: find_type_aux<Current + 1, Types...> // Strip off first, and search rest. Increment count
{};
// Specialization: If we didn't find a match
template <std::size_t Current, typename T>
struct find_type_aux<Current,T>
: std::integral_constant<std::size_t,static_cast<std::size_t>(-1)>{};
{};
// The interface: Find's "T" and returns the 0-based index.
template <typename T, typename...Types>
struct find_type : find_type_aux<0u,T,Types...>{};
有了这样的特征,找到的元素将是从 0 开始的索引,而未找到的元素将是static_cast<std::size_t>(-1)
. 1
由于您提到使用0
for not found 进行 1-indexed,因此 usingfind_type<int, Types...>::value + 1
将产生0
if not found (由于溢出)或1
-indexed 结果 - 根据要求。
1未明确定义为 1-indexed 的原因是,当前定义可以重用于在可变参数包中查找任何类型的索引 - 并且大多数使用包含可变参数的类型的接口都期望 0-indexing(例如作为std::get
)。这可以很容易地用作专门用于 的构建块int
,例如使用变量模板:
template <typename...Types>
constexpr auto find_int_v = find_type<int,Types...>::value + 1;
然后从以下产生正确答案:
int main() {
std::cout << find_int_v<short, long, char> << '\n';
std::cout << find_int_v<int, short, long, char> << '\n';
std::cout << find_int_v<short, long, char, int> << '\n';
return 0;
}
作为
0
1
4