Recursive template class and specialized base case are causing MSVC error C1001 (works fine on GCC and Clang)

Viewed 62

I would like to know why the following is rejected by MSVC and not Clang or GCC.
I adapted the code from a post I read about a while ago and was playing around with it.
There is no wider context, this is everything.
I had time to kill and my laptop, this was the result.

Basically it generates a compile time list of integers to aggregate initialize type T.

// Base case
template <int...LIST>
struct List<LAST_ARG , LIST...> // **** changing LAST_ARG to 8 fixes the problem ****
{   
    using Type_t = List<LIST...>;
};

// Recursive case
template <int PUSH_BACK, int...LIST>
struct List<PUSH_BACK, LIST...>
{   
    // **** CAUSES ERROR C1001! (Clang and GCC have no issues) ****
    using Type_t = typename List<PUSH_BACK+1, LIST..., PUSH_BACK+1>::Type_t;
};

Here's the full code.

#include <cstddef>
#include <iostream>

// THIS IS JUST A TEST CLASS
struct Vector
{
  float a=0, b=0, c=0, d=0, e=0, f=0, g=0, h=0, i=0;
  
  float operator[](std::size_t index) const { return *(&a + index); }
  
  void display() const
  {   std::cout << "[ ";
      for(std::size_t i = 0; i < 9; ++i)
          std::cout << this->operator[](i) << " ";
        std::cout << "]";
  }
};

template <typename T, int FIRST_ARG, int LAST_ARG>
struct MakeList
{
  static_assert(FIRST_ARG < LAST_ARG);

  static constexpr T init() noexcept
  { return do_init(typename List<FIRST_ARG-1>::Type_t());
  }

protected:
  // Base template
  template <int...LIST>
  struct List
  {};

  // Base case
  template <int...LIST>
  struct List<LAST_ARG , LIST...> // **** changing LAST_ARG to 8 fixes the problem ****
  { 
    using Type_t = List<LIST...>;
  };

  // Recursive case
  template <int PUSH_BACK, int...LIST>
  struct List<PUSH_BACK, LIST...>
  { 
        // **** CAUSES ERROR C1001! (Clang and GCC have no issues) ****
    using Type_t = typename List<PUSH_BACK+1, LIST..., PUSH_BACK+1>::Type_t;
  };

  template <int...INDEXES>
  static constexpr T do_init(List<INDEXES...>) noexcept
  { return{ INDEXES... };
  }
};

int main()
{
  const Vector v = MakeList<Vector, 0, 8>::init();
  
  v.display();
}

Live Demo on Compiler Explorer

0 Answers
Related