为什么编译器抱怨这不是constexpr?

时间:2016-06-29 15:10:30

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

我正在尝试学习如何在实践中使用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

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

1 个答案:

答案 0 :(得分:13)

[basic.types]/p10声明:

  

类型是文字类型,如果它是:

     
      
  • 可能是cv-qualified void;或

  •   
  • 标量类型;或

  •   
  • 参考类型;或

  •   
  • 一个文字类型的数组;或

  •   
  • 可能具有cv资格的类类型(条款[class]),它具有以下所有属性:

         
        
    • 它有一个简单的析构函数,

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

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

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

    •   
  •   

[class.dtor]/p5说:

  

如果析构函数不是用户提供的,并且如果:

,则析构函数很简单      

(5.4) - 析构函数不是virtual

     

(5.5) - 其类的所有直接基类都有简单的析构函数,并且

     

(5.6) - 对于类类的所有非静态数据成员(或其数组),每个都是这样的   class有一个简单的析构函数。

     

否则,析构函数非平凡

换句话说,要声明constexpr Matrix实例,它必须是文字类型,并且作为文字类型,其析构函数必须是default ed,或者完全删除,所以:

~Matrix() = default;

或: