3

I have in class County.h constructor:

struct Country {
    Country(double**, int);
};

and in main I have graph[Size][Size] and I want to call the constructor for County.

int main() {
    double graph[Size][Size];
    Country c(graph, 0);
}

But its giving me error no matching function for call to ‘County::County(double [22][22], int)’

What I can do in order to solve this problem?

8
  • Have you tried casting the graph as such: County c((double **) graph, (int) size); ? Commented May 5, 2015 at 14:11
  • 2
    An array of arrays is not an array of pointers. Commented May 5, 2015 at 14:12
  • 1
    @JoeUrc I doubt reinterpreting the doubles as pointers will lead to anything useful. Commented May 5, 2015 at 14:21
  • @JoeUrc: Bad idea. Hacking around errors makes you do silent errors. Commented May 5, 2015 at 14:23
  • Any reason why you do not use a vector<vector<double>> ? Commented May 5, 2015 at 14:57

2 Answers 2

4

double [Size][Size] and double** are not at all the same type. That is what your compiler doesn't like.

Change your constructor prototype or the way you declare your array. But you cannot directly cast an array of array to a pointer of pointer.

struct Country {
    Country(double[Size][Size], int);
};

OR:

int main() {
    double** graph = new (double*)[Size];
    for (int i = 0; i < Size; ++i) {
        graph[i] = new double[Size];
    }
    Country c(graph, 0);

    // Don't forget to delete your graph then.
}

Note that the first one requires that you would know the size before your code start its execution (storing Size in a macro for instance), but the second one is longer to code, and you will have to manipulate more RAM memory, that can lead to mistakes if you are not careful.

Sign up to request clarification or add additional context in comments.

2 Comments

i think i created like your first solution but I didn't give Size
@Saif If in your Country.h, you coded your constructor taking a double ** parameter, it's not at all like if you just didn't gave a Size: It is a different variable type. A valid constructor here would be taking a double [x][x] with x in a Macro.
1

An alternative is to declare your constructor as a template and pass the array by (const) reference,

struct Country {
    template<size_t N>
    Country(double /*const*/ (&arr)[N][N], int);
};

In this way, the template will deduce the size of the array directly. Of course, the downside is that the above won't work with double pointers. The upside is that the compiler will strongly check the type and your program won't even compile if the array is not made of doubles (no conversions are being performed at type deduction) or if it is not square.

4 Comments

The trouble with this approach is, that it links pretty much everything that has to handle this array together into one compilation unit. But, yes, it seems to be the best that C++ can do. In that regard it's clearly inferior to C...
@cmaster I guess that's the price to pay for enforcing type safety.
@cmaster have to say I'm not very familiar with pure C. So you'd write the such function like void f(int m, int n, int x[m][n]){} and pass the dimensions? (I think you need at least to pass the dimensions). The problem is that it will allow passing arrays of different sizes and types (at least on my machine gcc only spits an warning).
Yes, that is the basic idea. Unfortunately, I have to realize that you are right, gcc does not check the types. I would guess that that's a deficiency of gcc, not of the standard, but I may be wrong. Theoretically, it would be possible to do all the required type-checking (you don't need to know what value an array size has to assert that two array types derived from the same variables are the same), but it does add quite a bit of compiler complexity, and VLAs are not the most heavily used feature.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.