Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy array in constexpr constructor

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.

like image 533
NO_NAME Avatar asked Nov 22 '14 23:11

NO_NAME


People also ask

How to copy array to another in c++?

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.

Can a constructor be constexpr?

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.

Are default constructors constexpr?

For types with trivial default constructors, default initialization does not compile in constexpr.


3 Answers

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.

like image 166
Anton Savin Avatar answered Sep 22 '22 04:09

Anton Savin


You can use std::array. Since it is an aggregate type I believe this will work.

like image 36
tohava Avatar answered Sep 22 '22 04:09

tohava


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;
}
like image 29
xiaodong Avatar answered Sep 23 '22 04:09

xiaodong