使用 c++17 的 constexpr if,我们可以获得索引查找函数的更易读/更易理解的实现(我从来没有设法理解这里的其他答案):
template<typename Target, typename ListHead, typename... ListTails>
constexpr size_t getTypeIndexInTemplateList()
{
if constexpr (std::is_same<Target, ListHead>::value)
return 0;
else
return 1 + getTypeIndexInTemplateList<Target, ListTails...>();
}
这可以按如下方式使用:
size_t index = getTypeIndexInTemplateList<X, Foo,Bar,X,Baz>(); // this will return 2
或者,如果您有可变模板类型并希望在其中获取索引:
template<typename... Types>
class Container
{
public:
size_t getIndexOfType<typename T>() { return getTypeIndexInTemplateList<T, Types...>(); }
};
...
Container<Foo, Bar, X, Baz> container;
size_t container.getIndexOfType<X>(); // will return 2
它的工作方式是递归地从列表中消除类型。所以第一个例子的调用顺序基本上是:
getTypeIndexInTemplateList<X, Foo, Bar,X,Baz>() // ListHead = Foo, ListTails = Bar,X,Baz
getTypeIndexInTemplateList<X, Bar, X,Baz>() // ListHead = Bar, ListTails = X, Baz
getTypeIndexInTemplateList<X, X, Baz>() // ListHead = X, so now we return. Recursive addition takes care of calculating the correct index
该函数是 constexpr,所以这将在编译时执行,它在运行时只是一个常量。
如果您请求列表中不存在的类型,它将产生编译错误,因为它会尝试使用太少的模板参数调用函数。当然,如果该类型不止一次出现,这只会返回列表中该类型的第一个实例的索引。