Reputation: 15996
I've just encountered code in the project dcraw that's causing the Visual Studio 2012 compiler to fail. It's of the following form:
void CLASS cubic_spline (const int *x_, const int *y_, const int len)
{
float A[2*len][2*len], b[2*len], c[2*len], d[2*len];
...
The problem is the creation of these variable length arrays on the stack. I've never really seen code like this -- is it possible to compile this in the Visual Studio compiler?
Upvotes: 2
Views: 257
Reputation: 300439
As mentioned, VLA (Variable-Length Arrays) are a C feature, and more to the point a C99 feature which Visual Studio does not support. On Linux, Clang and Gcc both support C99 (and C11 I believe) and allow this syntax in C++ as an extension.
In C++, you can easily transform the code by switching to std::vector<float>
for all simple arrays. Only A
will require a bit more work:
std::vector< std::vector<float> >
, but then you lose contiguity and localitystd::vector<float> A(2*len*2*len);
but then you will lose access by A[i][j]
which will have to be transformed into A[i*2*len + j]
insteadIn any case, you will need to update this code to make it work on Visual Studio.
EDIT: per your comment:
The function is called twice in the code, once as
cubic_spline(cx, cf, 9);
and once ascubic_spline(cx, cf, 18);
. In the first example,cx
andcy
areint[9]
and in the second example they'reint[18]
.
In this case you can actually make the function a template:
template <size_t len>
void CLASS cubic_spline(int const (&x)[len], int const (&y)[len]) {
float A[2*len][2*len], b[2*len], c[2*len], d[2*len];
}
Note that I removed the last parameter, because it is no longer necessary. The type of x
and y
is int const (&)[len]
which is a reference to an array of int const
of length len
.
Upvotes: 2
Reputation: 76308
There are working compiler extensions (such as Clang's one and GCC's one) that allow this, but it's not standard, yet.
In C++11 you can also use constexpr
if the numeric value is constant. And finally a proposal has been submitted to standardize it.
If x_
and y_
are meant to be arrays, you can just use std::array
as follows:
template<std::size_t size>
void CLASS cubic_spline (std::array<int, size> const& x, std::array<int, size> const& y)
{
using float_array = std::array<float, 2 * size>;
std::array<float_array, 2 * size> A;
float_array b, c, d;
// ...
}
This way you could ensure that the passed arrays dimensions are equal, at compile time.
Otherwise you can clean that up with std::vector
:
void CLASS cubic_spline (std::vector<int> const& x, std::vector<int> const& y)
{
std::vector<std::vector<float>> A(2 * x.size());
std::vector<float> b, c, d;
// ...
}
Upvotes: 2
Reputation: 27548
This is a GCC-specific compiler extension, see Arrays of Variable Length. I am not aware of any compiler options to make them work out of the box in VC. If this is a very isolated problem, try preprocessor #ifdef
s to serve different code to VC.
Upvotes: 1