Tyler Kelly
Tyler Kelly

Reputation: 574

Variable length array error with constexpr

I have a class with a member function which declares an array whose size is based off a formula.

template <int SIZE>
class Example{
   constexpr int lookup(const int n) const
   {
      return n * n + n;
   }
   inline void func()
   {
       double array[lookup(SIZE)];
   }
};

This gives me the vla error. I think it should work because SIZE is resolved at compile time, and lookup is a constexpr. I know the following will work:

template <int SIZE>
class Example{

   inline void func()
   {
       constexpr int sz = SIZE * SIZE + SIZE;
       double array[sz];
   }
};

I guess I'm just trying to figure out why

EDIT Sorry for the typos, was trying to just write a smaller example and ended up with the missing n and class name.

Upvotes: 0

Views: 685

Answers (2)

max66
max66

Reputation: 66200

It's complicated...

First of all, some compilers (see MikeCAT answer and Bill Lynch linked example) can compile the following code (if you give a name to the class and correct lookup() naming n the argument)

inline void func()
{
    double array[lookup(SIZE)];
}

because they support a C99 extension that accept the "variable length array" feature.

But this extension isn't standard C++.

You can verify this modifying func() as follows (almost equivalent, in standard C++)

inline void func()
{
    constexpr int s = lookup(SIZE);

    double array[s];
}

and this can't compile if lookup() is a non-static method

Consider that

 lookup(SIZE);

is a short form for

 this->lookup(SIZE);

I mean... the use of lookup() involve an object of your class.

The problem is that your func() method is available for both constexpr and non-constexpr objects.

Suppose you have a non-constexpr object: calling func() from it you impose that

constexpr int s = this->lookup(SIZE);

is evaluated compile-time.

That is: you impose that the this pointer (so the object itself) is available compile-time.

This is clearly impossible for run-time created objects, so your code can't compile.

Different if you declare lookup() as a static method: this way, calling lookup() doesn't involve an object of your class so your code can compile.

Upvotes: 3

MikeCAT
MikeCAT

Reputation: 75062

  • Class template must have a name.
  • n is not declared in lookup.

This should work as C++11:

template <int SIZE>
class hoge { // add hoge
   constexpr int lookup(const int n) const // add n
   {
      return n * n + n;
   }
   inline void func()
   {
       double array[lookup(SIZE)];
   }
};

Upvotes: 0

Related Questions