我有一个类Index
类似于std::integer_sequence
:
template<std::size_t... NValues>
struct Index { };
我想用序列N-1, N-2,…, 2, 1, 0.
template<std::size_t N>
struct MakeIndex
{
private:
template<std::size_t I, std::size_t... NIndexValues>
struct _Make;
public:
using Type = typename _Make<N>::Type;
private:
template<std::size_t I, std::size_t... NIndexValues>
struct _Make
{
using Type = typename _Make<I - 1, NIndexValues..., I - 1>::Type;
};
template<std::size_t... NIndexValues>
struct _Make<0, NIndexValues...>
{
using Type = Index<NIndexValues...>;
};
};
int main()
{
using T = MakeIndex<5>::Type;
}
在clang编译器(3.7.0)上,它产生
例子致命错误:递归模板实例化超过最大深度256年的
它在VS和GCC上工作得很好。也许我做错了什么?还是编译器的bug?
看起来像一个clang编译器错误。如果不使用前向声明,它也会在clang:
上编译。template<std::size_t N>
struct MakeIndex
{
private:
template<std::size_t I, std::size_t... NIndexValues>
struct _Make
{
using Type = typename _Make<I - 1, NIndexValues..., I-1>::Type;
};
template<std::size_t... NIndexValues>
struct _Make<0, NIndexValues...>
{
using Type = Index<NIndexValues...>;
};
public:
using Type = typename _Make<N>::Type;
};
生活例子
它看起来像一个编译器错误,虽然我不确定问题是否与clang或gcc和msvc有关。
看起来clang在以0调用时不会使用模板特化。(你可以添加一个静态断言,使错误更容易读)。
您所面临的问题与您所定义的using
有关。在编译器解析这个用法的时候,它只知道_Make
的一个定义,它不是专门化的,在实例化模板时,它只使用这个信息。如果我们提前添加专门化,它将编译。
生活例子
由于GCC在没有前向声明的情况下无法编译,因此有声明是查找的必要条件,所以我猜GCC正在解析一个实际上当时没有声明的类,这很可能是不应该做的。
然而,为了确保正确的行为,我建议只记录一个错误。如果它不是编译器中的错误,它被记录了,他们很可能会解释为什么另一个错误,你可以用它来记录第二个错误。