0

I have a function in C++ that looks like:

//ellipsis are irrelevant variables. Not variadic
lint find_max(const void* ptr, ... , const vector<lint> &nums, ...)
{
    const mm (*arr)[nums.size()] = (const mm (*)[nums.size()]) ptr;
    //or
    const mm (*arr1)[nums.size()] = reinterpret_cast<const mm (*)[nums.size()]>
                                      (ptr);
}


The two casts produce an error with little detail as to why.

 error: cannot convert ‘const mm (*)[(<anonymous> + 1)]’ {aka ‘const min_and_max (*)[(<anonymous> + 1)]’} to ‘const mm (*)[(<anonymous> + 1)]’ {aka ‘const min_and_max (*)[(<anonymous> + 1)]’} in initialization
   42 |   const mm (*arr)[nums.size()] = (const mm(*)[nums.size()])ptr;
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                  |
      |                                  const mm (*)[(<anonymous> + 1)] {aka const min_and_max (*)[(<anonymous> + 1)]}

If I am not mistaken, both lvalue type and the corresponding cast is similar. For future reference, should I have more than 2 dimensions, how can I add them? I'm still an amateur in pointer manipulation so this will help alot.

EDIT this does not produce any errors in g++:

typedef long long int lint;

lint pInf = ~((unsigned long long int)0) >> 1;
lint nInf = ~pInf;

typedef struct min_and_max
{
    lint min{pInf};
    lint max{nInf};
}mm;


const lint find_max(const void* ptr, int i, int j, const vector<lint> &nums, 
                    const vector<char> &ops)
{
    const int dim = nums.size();
    const mm (*arr)[dim] = reinterpret_cast<const mm (*)[dim]>
                                      (ptr);

    //algorithm which I haven't figured out yet.
    some_lint_value = arr[i][j].max + arr[i-232414][j+46846].min;

    return some_lint_value;
}

void caller(vector<lint> &nums, vector<char> &ops)
{
    mm arr[ops.size()][nums.size()]; //ISO variable size forbid warn

    for (int i = 1; i <= ops.size(); i++)
      {
         for (int j = 1; j <= nums.size(); j++)
           //looped logic for solving the max/min value for an expression problem
           arr[i][j].max = find_max(arr, i, j, nums, ops);
      }
}
Silver Flash
  • 871
  • 3
  • 7
  • 16
  • 2
    In C++, array bounds must be constant expressions. – aschepler Apr 11 '20 at 01:02
  • 1
    One of the major features of C++ is its strong type-safety. Attempting to defeat it, by playing games with `void *`, will only result in headaches, mysterious bugs, and crashes. It is unclear what this is supposed to do, but one thing is clear: whatever is attempted here, it should be scrapped and rewritten from scratch, without any messy `void *`s, and with strong type-safety. The only practical reason for using `void *` is when there's a need to interact with legacy C code. – Sam Varshavchik Apr 11 '20 at 01:02
  • Since this involves a gcc extension, it might take a gcc guru to provide a definitive answer. My speculation based upon the error message is that the compiler has to account for the possibility that a function need not return the same value when called multiple times with the same parameters. So a dimension of "" cannot match any other dimension, not even another "". – JaMiT Apr 11 '20 at 03:37
  • `nums` is not used in find_max except to get the size of the vector, is that correct? In the sample caller code `arr` never has any values assigned to it, but `find_max` reads them. Is `arr` supposed to be poplated from `nums` and `ops` in the caller somehow? It's not clear to me what the relationship between nums, ops and arr is – M.M Apr 11 '20 at 03:54
  • I didn't add complicated and possibly bogus logic which would complicate the example. But my dp table (`arr`) is filled with processed `nums` and `ops` values. I need the two input-data vectors for both functions (at least in this iteration). In other words, assume that I use nums ,besides its use in identifying the dimension, and arr has been initialized to default infinity values. – Silver Flash Apr 11 '20 at 04:04
  • If you are curious of what the end result should look like : ("https://www.geeksforgeeks.org/minimum-maximum-values-expression/"). I am getting there on my own. Please don't spoil! – Silver Flash Apr 11 '20 at 04:17

1 Answers1

1

In Standard C++ the array bounds must be constant expressions. Both of your examples are ill-formed.

The difference in compiler behaviour you observe relates to a non-standard extension provided by your compiler that evidently treats the two cases different; consulting your compiler's documentation might be a way to proceed if you want to go further down that avenue.

Of course my advice would be to use standard constructs, then it will work on every compiler and the behaviour is well-documented.


The simplest solution to the requirement of "create a contiguous 2-D array with variable dimensions and pass by reference to a function" is actually to create a vector and bear with the minor inconvenience of using x + y*COLS instead of [x][y] for accessing it.

The code might look like (pseudocode):

lint find_max(vector<mm> &arr2, vector<lint> const& nums, ....otherstuff)
{
    mm& item_at_x_y = arr2[x + y * nums.size()];
}

with caller:

void caller()
{
     vector<mm> arr2( nums.size() * ops.size() );
     // populate arr2...
     find_max(arr2, nums, ops...);
}

It would be possible to write a Matrix-like class that allows the [x][y] access syntax, e.g. see here or google for more examples.

You could make an accessor for using parentheses syntax, e.g.:

auto arr = [&](size_t y, size_t x) { return arr2[x + y * nums.size()]; };

arr(3, 4) = 5;
M.M
  • 138,810
  • 21
  • 208
  • 365
  • Do you mean that the `int dim` parameter should be a const. Or that it should be a hard-coded value? The compiler is g++ – Silver Flash Apr 11 '20 at 02:01
  • You are correct. I enabled all warnings and enforced c++14 std here and got 2 warnings pointing at (*arr) and dim even though I made it `const int dim`. How can I make the code >c++14 compliant? – Silver Flash Apr 11 '20 at 02:21
  • @SilverFlash the expression inside the `[ ]` in a declarator must be a constant expression – M.M Apr 11 '20 at 02:39
  • To get an answer for "How can I make the code >c++14 compliant?" you would have to add more explanation to the question about what the function is supposed to do (having a sample call site would be useful too) – M.M Apr 11 '20 at 02:40
  • The contiguous vector with manual calculation of index; how safe is it in terms of overflow? Given the pseudo-polynomial complexity of the dp algorithm, this program is only going to be stress-tested for less than 30-40 inputs. I assume this cannot be applied in a general case unless the `[]` operator has a 64bit int overload. – Silver Flash Apr 11 '20 at 06:03
  • 1
    @SilverFlash it should be `size_t` type – M.M Apr 11 '20 at 06:19