【问题标题】:Why does the compiler complain about this not being a constexpr?为什么编译器抱怨这不是 constexpr?
【发布时间】:2016-11-01 09:30:56
【问题描述】:

我正在尝试更多地了解如何在实践中使用 C++ 常量表达式,并创建了以下 Matrix 类模板用于说明目的:

#include <array>

template <typename T, int numrows, int numcols>
class Matrix{
public:
    using value_type = T;
    constexpr Matrix() : {}
   ~Matrix(){}

    constexpr Matrix(const std::array<T, numrows*numcols>& a) :
        values_(a){}

    constexpr Matrix(const Matrix& other) :
        values_(other.values_){

    }

    constexpr const T& operator()(int row, int col) const {
        return values_[row*numcols+col];
    }

    T& operator()(int row, int col){
        return values_[row*numcols+col];
    }

    constexpr int rows() const {
        return numrows;
    }

    constexpr int columns() const {
        return numcols;
    }


private:
    std::array<T, numrows*numcols> values_{};
};

这个想法是有一个简单的 Matrix 类,我可以在编译时使用它来计算小矩阵来评估 Matrix 表达式(请注意,我还没有实现用于加法和乘法的常用 Matrix 运算符)。

当我尝试如下初始化一个 Matrix 实例时:

constexpr std::array<double, 4> a = {1,1,1,1};
constexpr Matrix<double, 2, 2> m(a);

我从编译器 (MS Visual C++ 14) 收到以下错误:

error: C2127: 'm': illegal initialization of 'constexpr' entity with a non-constant expression

请注意我做错了什么......任何帮助完成这项工作将不胜感激!

【问题讨论】:

  • 也许std::array 没有 constexpr 复制构造函数?
  • 去掉析构函数的定义
  • 作为旁注,没有必要将numrows_numcols_ 存储为成员变量。由于您已经将这些值作为模板参数,因此只需返回这些值。
  • @Piotr Skotnicki 是的,成功了。谢谢!如果您将此作为答案发布,我会接受。但是我不明白为什么定义析构函数会触发错误?
  • @nasser-sh 正如建议的那样,我通过删除行和列大小的不必要成员变量来清理代码

标签: c++ c++11 visual-c++ constexpr


【解决方案1】:

[basic.types]/p10 声明:

一个类型是一个文字类型如果它是:

  • 可能是 cv 合格的void;或

  • 标量类型;或

  • 引用类型;或

  • 文字类型的数组;或

  • 具有以下所有属性的可能具有 cv 限定的类类型(子句 [class]):

    • 它有一个微不足道的析构函数,

    • 它要么是闭包类型 ([expr.prim.lambda]),要么是聚合类型 ([dcl.init.aggr]),或者具有至少一个 constexpr 构造函数或构造函数模板(可能从基类继承 ([namespace.udecl]))那不是复制或移动构造函数,

    • 如果是联合,则其非静态数据成员中至少有一个是非易失文字类型,并且

    • 如果不是联合,则它的所有非静态数据成员和基类都是非易失文字类型。

[class.dtor]/p5 表示:

如果析构函数不是用户提供的并且满足以下条件,则它是微不足道的:

(5.4)——析构函数不是virtual

(5.5) — 其类的所有直接基类都有微不足道的析构函数,并且

(5.6) — 对于其类的所有属于类类型(或其数组)的非静态数据成员,每个这样的 类有一个微不足道的析构函数。

否则,析构函数是非平凡的

换句话说,要声明Matrixconstexpr 实例,它必须是文字类型,并且要成为文字类型,它的析构函数必须是defaulted,或者完全删除,所以:

~Matrix() = default;

或:

 

【讨论】:

  • 非常感谢您的澄清!
  • 我喜欢。 :-)
猜你喜欢
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
  • 2012-03-28
  • 2012-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
相关资源
最近更新 更多