15

I try to compile very simple code:

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const int as[3] = { 5, 6, 7, };
    const T t {
        as, 2, 3,
    };
    return 0;
}

But it gives me very strange errors:

t.cpp: In function 'int main()':
t.cpp:11:5: error: array must be initialized with a brace-enclosed initializer
     };
     ^

As from what I understand the compiler wants me to initialize everything in one single place. How do I initialize fields separately and then use them during initiliazation the structure later?

6
  • 4
    std::array to the rescue. Commented Sep 14, 2017 at 6:52
  • 3
    You can't do that with plain arrays. Are you allowed to modify T? Commented Sep 14, 2017 at 6:53
  • @juanchopanza I would like to have only costs as possible in my code and to avoid mutation only for initialization of the object, this is my principle.. So The question here is to initialize a const object. Commented Sep 14, 2017 at 6:53
  • 3
    @VictorPolevoy I think that what juanchopanza is asking is if you can change the member a ot the structure T to be of a different type? For example std::array<int, 3> a;? Commented Sep 14, 2017 at 6:55
  • @Someprogrammerdude Oh, excuse me then. Yes, I can change it to everything, this is my own structure. Commented Sep 14, 2017 at 6:56

4 Answers 4

22

Arrays are neither copy-constructible nor copy-assignable. If you have access to C++11 and newer, you could use std::array.

#include <array>

struct T {
    std::array<int, 3> a;
    int b;
    int c;
};

int main() {
    const std::array<int,3> as = { 5, 6, 7, };
    const T t {
        as, 2, 3,
    };
    return 0;
}

Otherwise you will have to roll a loop and copy the elements individually.

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

1 Comment

Or you could use nested braced initializer lists
11

C++ arrays are not copy constructible, so compilation will fail. However,

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const T t {
        {5, 6, 7, }, 2, 3,
    };
    return 0;
}

is an alternative, although it does discard the explicit as variable.

Reference: http://en.cppreference.com/w/cpp/concept/CopyConstructible

1 Comment

This solution though, is unrealistic when it comes to larger arrays.
2

As from what I understand the compiler wants me to initialize everything in one single place.

This is because array types decay into pointer types and then the compiler tries to assign a pointer to an array type.

How do I initialize fields separately and then use them during initiliazation the structure later?

You can use pointer types in the structure (which I would not advise). Or you can use container classes instead (STL).

Comments

0

You can also do this, but it assumes your T t data is not really const as I remove its constness with const_cast<>()

#include <cstdio>
#include <cstring>
#include <algorithm>

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const int as[3] = { 5, 6, 7, };

    const T t {
        {0}, 2, 3,
    };

    memcpy( reinterpret_cast< void* >( const_cast< int* > ( t.a ) ), 
            reinterpret_cast< const void* >( as ), 
            std::min( sizeof t.a, sizeof as ) );

    printf( "t.a: '%d, %d, %d'\n", t.a[0], t.a[1], t.a[2] );
    return 0;
}

If you data T t is not actually const, you can do it without the const_cast<>()

#include <cstdio>
#include <cstring>
#include <algorithm>

struct T {
    int a[3];
    int b;
    int c;
};

int main() {
    const int as[3] = { 5, 6, 7, };

    T t {
        {0}, 2, 3,
    };

    memcpy( reinterpret_cast< void* >( t.a ),
            reinterpret_cast< const void* >( as ), 
            std::min( sizeof t.a, sizeof as ) );

    printf( "t.a: '%d, %d, %d'\n", t.a[0], t.a[1], t.a[2] );
    return 0;
}

I am adding the reinterpret_cast<>() because memcpy() requires a void*

function void * memcpy ( void * destination, const void * source, size_t num );

Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination. http://www.cplusplus.com/reference/cstring/memcpy/

I am also doing std::min( sizeof t.a, sizeof as ) to avoid override any data it should not in case the source array is way bigger than expected.

And finally, {0} is initializing by default the destine array with zeros. It could also be {} to not initialize anything and let the default values to be trash memory/random data.

References:

  1. When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
  2. Should I use static_cast or reinterpret_cast when casting a void* to whatever
  3. When to use reinterpret_cast?
  4. Should I use a C++ reinterpret_cast over a C-style cast?
  5. Use of min and max functions in C++

Comments

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.