4
struct S {
    double arr[1];
    S(double arr[1]) : arr(arr) {}
};

int main(void) {
    double arr[1] = {1.2};
    S p(arr);
    return 0;
}

Hi, this is an extracted problem I encountered in my code.

Do you know why this code won't compile?

main.cpp: In constructor ‘S::S(double*)’:
main.cpp:26:28: error: incompatible types in assignment of ‘double*’ to ‘double [1]’
  S(double arr[1]) : arr(arr) {}

I am using g++, compiling and running with

 g++ -std=c++17 main.cpp kdtree.h kdtree.cpp && ./a.out
7
  • What compiler are you using? Commented Dec 29, 2017 at 20:21
  • @Mad Physicist Hi, g++. This is the command that I use: g++ -std=c++17 main.cpp kdtree.h kdtree.cpp && ./a.out Commented Dec 29, 2017 at 20:23
  • Here's an IDEOne link: ideone.com/y18tuc. I made the same edit independently. Commented Dec 29, 2017 at 20:23
  • 1
    I edited your question with the relevant info. In general, don't reply with anything that might be relevant in comments. Edit the question instead. Commented Dec 29, 2017 at 20:24
  • That being said, I have no idea what the answer is, but I'm very curious to find out. +1 Commented Dec 29, 2017 at 20:25

4 Answers 4

7

Arrays can't be copied.

int a[3];
int b[3];
a = b; // illegal

Further, when you pass an array to a function, its name decays to a pointer, so S(double arr[1]) is equivalent to S(double* arr). Once you're inside the function, you have to copy the individual elements, so you also need the size of the array:

S(double *x, std::size_t sz) {
    std::copy_n(x, sz, arr);
}

You can omit the size if you write the template as a function:

template <std::size_t sz)
S(double (&x)[sz]) {
    std::copy_n(x, sz, arr);
}

Or, even better, use std::array, which works the way you expect.

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

2 Comments

Thanks! Got it now. Is there performance loss in using the array wrapper?
@DanZilberman there isn't. It's mandated to be POD (even though some MSVC (library) versions fail to report it as such AFAIR)
6

Do you know why this code won't compile?

It won't compile because arrays cannot be copy-initialized (except copy-list-initialized, but you're not doing that).

Arrays have to be copied one element at a time, using a loop. There's also a standard algorithm for copying so you don't need to write that loop yourself: std::copy.

Or, you can use std::array that was introduced in C++11. std::array is copyable.

Comments

3

You can't. What you can do is use the std::array wrapper instead:

struct S {
    std::array<double, 1> arr;
    S(std::array<double, 1> arr) : arr(arr) {}
};

Comments

3

Although the signature of a constructor is written like that, the array type is adjusted to a pointer, and the array argument decays to a pointer to its first element.

However, the arr member in the struct is still of type array. And a pointer can't be assigned to an array (hence the error).

It's also not possible to assign one array to another (e.g. even if you change it to one of the ways described in the above link), so you need to copy the elements manually with a loop, or using std::copy, or use std::array, as in Ron's answer.

2 Comments

In the signature, the array type is adjusted to pointer. Decay takes place when passing an array to such a function when calling it (or any case of assigning an array name to a pointer.)
@juanchopanza Hmm. Is that better?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.