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