I wrote a class with a constexpr copy constructor. (It is a struct in example to make it simpler.) One of the fields is an array. I want copy it too.
struct Foo
{
    static constexpr int SIZE = 4;
    constexpr Foo() = default;
    constexpr Foo(const Foo &foo) :
            arr{foo.arr[0], foo.arr[1], foo.arr[2], foo.arr[3]},
            bar(foo.bar+1) {}
    int arr[SIZE] = {0, 0, 0, 0};
    int bar = 0;
};
My version works but it isn't scalable. If I change SIZE, I have to modify the constructor. In addition, code looks ugly.
Is it any better way to copy array in constructor? Constructor must be constexpr.
In C++ an array can be copied manually (by hand) or by using the std::copy() function, from the C++ algorithm library. In computer programming, there is shallow copying and there is deep copying. Shallow copying is when two different array names (old and new), refer to the same content.
A constructor that is declared with a constexpr specifier is a constexpr constructor. Previously, only expressions of built-in types could be valid constant expressions. With constexpr constructors, objects of user-defined types can be included in valid constant expressions.
For types with trivial default constructors, default initialization does not compile in constexpr.
In C++14 you can just use a loop to copy the array:
constexpr Foo(const Foo &foo)
    : bar(foo.bar + 1)
{
    for (int i = 0; i < SIZE; ++i)
        arr[i] = foo.arr[i];
}
That doesn't mean you should do it. I'd recommend to use std::array instead. For example, if arr is an array of some class type with non-trivial initialization, it would be default-initialized and then copied, thus wasting performance, instead of copy-initialization when using std::array and default copy constructor.
You can use std::array. Since it is an aggregate type I believe this will work.
you can do something like in C++11 to just copy the array
template <int LENGTH>
constexpr bool copy_array(const char (&from)[LENGTH + 1], char (&to)[LENGTH], int index)
{
    return index < LENGTH ?  (to[index] = from[index], copy_array(from, to, ++index)) : false;
}
constexpr char src[] = "ab";
char dest[2];
copy_array(src, dest, 0);
edited: And in your context, you might be able to do something like:
#include <iostream>
#include <type_traits>
#include <array>
#include <utility>
struct Foo
{
    static constexpr int SIZE = 4;
    constexpr Foo() = default;
    constexpr Foo(const Foo &foo) :
            arr{foo.arr},
            bar(foo.bar + 1) {}
    std::array<int, SIZE> arr = {{0, 0, 0, 0}};
    int bar = 0;
};
int main()
{
    constexpr Foo foo1;
    constexpr Foo foo2(foo1);
    std::cout << foo1.bar << std::endl;
    std::cout << foo2.bar << std::endl;
    return 0;
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With