I have the struct and a template as below:
template <const int nrow, const int ncol>
struct Mat{
const int row_size = nrow;
const int col_size = ncol;
std::array<std::array<float, ncol>, nrow> mat;
};
I want to sort the matrix produced by Mat
struct, so I did:
int main(int argc, const char * argv[]) {
Mat<3, 3> mat;
mat.mat = {{{1,2,3},{4,5,6},{7,8,9}}};
std::sort(std::begin(mat.mat), std::end(mat.mat),
[](std::array<float, mat.col_size>& c1, std::array<float, mat.col_size>& c2){return c1[0]>c2[0];});
}
However, I get this error:
Non-type template argument is not a constant expression
and this expression,mat.col_size
, in sort is underlined red in XCode.
In the struct I made the col_size
a constant but it did not help. However, if I add static
keyword before it, then it works fine.
Why was there this error and what static
does?
CodePudding user response:
You declared row_size
and col_size
as non-static data members, so although they are const
, they can still be initialized to any value in any given instance of the class. The default member initializer is used only if no other value is given e.g. in an aggregate initialization.
However you are trying to use these values as template arguments (e.g. in std::array<float, mat.col_size>
), which must be known at compile-time. More specifically the template argument must be a "constant expression", so the members must be "usable in constant expressions". So they can't be object-dependent, at least as long as the class object itself is not a compile-time constant, aka "usable in constant expressions" by being declared constexpr
, and must be static:
static const int row_size = nrow;
static const int col_size = ncol;
For const int
with initializer this is sufficient for their values to be considered compile-time constants (aka. "usable in constant expressions"). For non-integral/enumeration types, you will need to replace const
with constexpr
. (Integral and enumeration types are an exception not requiring constexpr
for historical reasons.)
CodePudding user response:
You are looking for static constexpr
(compile-time constant expression), not const
- which might even be something set in, e.g., ctor using run-time values.
template <const int nrow, const int ncol>
struct Mat{
static constexpr int row_size = nrow;
static constexpr int col_size = ncol;
std::array<std::array<float, ncol>, nrow> mat;
};