叮当声.致命错误:递归模板实例化超出最大深度



我有一个类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正在解析一个实际上当时没有声明的类,这很可能是不应该做的。

然而,为了确保正确的行为,我建议只记录一个错误。如果它不是编译器中的错误,它被记录了,他们很可能会解释为什么另一个错误,你可以用它来记录第二个错误。

最新更新