2

I was looking around how to make a lookup table and found this simple and elegant answer.

I didn't want to necro the thread, so I thought I'd make a new question. When trying to compile that answer in VS2015 I get the following errors:

template<int N>
struct Table
{
  constexpr Table() : values()
  {
    // C3538 auto must always deduce the same type 
    // C3250 i declaration is not allowed in constexpr body
    // C3249 illegal statement for sub-expression 'constexpr' function
    for (auto i = 0; i < N; ++i)
    {
        values[i][0] = i;
        values[i][1] = i * i * i;
    }
  }
  int values[N][2];
};

int main(){
  // defctor does not produce a constant value 
  constexpr auto a = Table<1000>();
  return 0;
}

I tried to replace the C style array with an std::array because I thought that might help with the iteration process. I also checked the code on some online compiler and it works there but not in VS.

What's the problem, and how could I replicate the solution without template bloating the code?

Null
  • 1,950
  • 9
  • 30
  • 33
val
  • 729
  • 6
  • 19
  • 7
    The reason for the messages is that VS2015 doesn't implement C++14 constexpr. You will have to wait for the next release. – Bo Persson Oct 26 '16 at 07:13
  • 3
    Your constructor is a valid C++14 [`constexpr` constructor](http://en.cppreference.com/w/cpp/language/constexpr). However Visual Studio is probably a little late as usual when following the latest standard, and only allows the C++11 variant, which is much more restrictive. – Some programmer dude Oct 26 '16 at 07:14
  • As an aside, your code currently compiles with [the online version of MSVC 2015](http://webcompiler.cloudapp.net/). It appears that their C++14 `constexpr` support took a big step forwards only a few days after you asked. – Justin Time - Reinstate Monica Nov 22 '16 at 18:42

1 Answers1

3

As indicated in the comments above, MSVC 2015 doesn't support C++14 constexpr, but it does support lots of other C++14 features, so you can do this:

#include <cstddef>
#include <utility>

template<int N> struct Table
{
   constexpr Table() : Table(std::make_index_sequence<N>{}) { }
   int values[N][2];
private:
   template<std::size_t... Is> constexpr Table(std::index_sequence<Is...>)
      : values{{Is, Is * Is * Is}...} { }
};

int main()
{
   constexpr auto a = Table<100>{};
   static_assert(a.values[77][0] == 77 && a.values[77][1] == 77 * 77 * 77, "oops");
}

IntelliSense still complains about the initialization of a, but that's a bug. MSVC accepts the code (and so do Clang and GCC in C++14 mode).

Note that using a large value for N (Table<1000>) as in the original code will generate a warning:

warning C4503: 'Table<1000>::Table': decorated name length exceeded, name was truncated

As far as I can tell from reading the docs, the warning can safely be ignored in this context.

bogdan
  • 9,229
  • 2
  • 33
  • 48