首页 > 解决方案 > constexpr 的可变长度数组错误

问题描述

我有一个带有成员函数的类,它声明了一个大小基于公式的数组。

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

这给了我 vla 错误。我认为它应该可以工作,因为SIZE在编译时已解决,并且查找是constexpr. 我知道以下将起作用:

template <int SIZE>
class Example{

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

我想我只是想弄清楚为什么

编辑对不起拼写错误,试图只写一个更小的例子,结果丢失了n类名。

标签: c++arraysc++11template-meta-programmingconstexpr

解决方案


情况很复杂...

首先,一些编译器(请参阅 MikeCAT 答案和 Bill Lynch 链接示例)可以编译以下代码(如果您为类命名并正确lookup()命名n参数)

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

因为它们支持接受“可变长度数组”功能的 C99 扩展。

但是这个扩展不是标准的 C++。

func()您可以按如下方式验证此修改(几乎等效,在标准 C++ 中)

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

    double array[s];
}

lookup()如果是非静态方法,则无法编译

考虑到

 lookup(SIZE);

是一个简短的形式

 this->lookup(SIZE);

我的意思是......使用lookup()涉及你班级的一个对象。

问题是您的func()方法对对象constexpr和非constexpr对象都可用。

假设你有一个非constexpr对象:从它调用func()你强加

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

在编译时进行评估。

也就是说:您强制this指针(因此对象本身)在编译时可用。

这对于运行时创建的对象显然是不可能的,因此您的代码无法编译。

如果您声明lookup()static方法则不同:这样,调用lookup()不涉及您的类的对象,因此您的代码可以编译。


推荐阅读