对于我正在从事的项目,我一直在尝试实现一个以模板类作为可能类型的类型列表,我的实现的相关部分如下。它通常运行良好,但当我将一些实用程序类型/操作组合在一起时,它无法按预期运行。
// template class typelist
template <template <class> class ... TemplateTypes>
struct TemplateTypeList {};
// utility types for TemplateTypeList
// type at index of typelist
template <std::size_t I, class TypeList>
struct TemplateTypeListType;
template <template <class> class First, template <class> class ... RestOfTypeList>
struct TemplateTypeListType<0, TemplateTypeList<First, RestOfTypeList...>> {
template <class T>
using result = First<T>;
};
template <std::size_t I, template <class> class First, template <class> class ... RestOfTypeList>
struct TemplateTypeListType<I, TemplateTypeList<First, RestOfTypeList...>> {
template <class T>
using result = typename TemplateTypeListType<I - 1, TemplateTypeList<RestOfTypeList...>>::template result<T>;
};
// index of type in typelist
template <template <class> class TypeToFind, class TypeList>
struct TemplateTypeListIndex;
template <template <class> class TypeToFind, template <class> class ... RestOfTypes>
struct TemplateTypeListIndex<TypeToFind, TemplateTypeList<TypeToFind, RestOfTypes ...>> {
static const int result = 0;
};
template <template <class> class TypeToFind, template <class> class First, template <class> class ... RestOfTypes>
struct TemplateTypeListIndex<TypeToFind, TemplateTypeList<First, RestOfTypes...>> {
private:
using ResultOfPrior = TemplateTypeListIndex<TypeToFind, TemplateTypeList<RestOfTypes...>>;
public:
static const int result = ResultOfPrior::result == -1 ? -1 : ResultOfPrior::result + 1;
};
template <template <class> class TypeToFind>
struct TemplateTypeListIndex<TypeToFind, TemplateTypeList<>> {
static const int result = -1;
};
该实现对于我的大多数情况都工作正常,但是当我使用
TemplateTypeListIndex
并得到 TemplateTypeListType
的结果时,它似乎不起作用,这是一个示例:
template <class T>
struct Class1 {};
template <class T>
struct Class2 {};
using Types = TemplateTypeList<Class1, Class2>;
int index = TemplateTypeListIndex<TemplateTypeListType<0, Types>::result, Types>::result;
ASSERT_EQ(index, 0); // fails, index == -1
我很困惑,因为它几乎适用于我用过的所有其他情况。我对模板专业化所做的一些假设是否不正确,导致了这个问题?
正如评论中所指出的,这似乎是 C++ 规范中 temp.alias 部分的结果,该部分基本上规定模板别名不能相等,只有模板特化可以相等。为了解决这个问题,我在
TemplateTypeListIndex
中创建了一个虚拟专业化,现在将 TemplateTypeListType
与 TemplateTypeListIndex
结合使用:
// index of type in typelist
template <template <class> class TypeToFind, class TypeList>
struct TemplateTypeListIndex;
template <template <class> class TypeToFind, template <class> class First, template <class> class ... RestOfTypes>
struct TemplateTypeListIndex<TypeToFind, TemplateTypeList<First, RestOfTypes...>> {
private:
using ResultOfPrior = TemplateTypeListIndex<TypeToFind, TemplateTypeList<RestOfTypes...>>;
template <class T>
using IsMatch = std::is_same<TypeToFind<T>, First<T>>;
struct Dummy {};
public:
static const int result = IsMatch<Dummy>::value ? 0 : ResultOfPrior::result == -1 ? -1 : ResultOfPrior::result + 1;
};
template <template <class> class TypeToFind>
struct TemplateTypeListIndex<TypeToFind, TemplateTypeList<>> {
static const int result = -1;
};
我现在意识到,由于 temp.alias 的原因,需要谨慎使用
TemplateTypeListType::result
,并且我应该只使用结果的特化来比较模板特化中的类型。