Yet again, C++17's guaranteed copy elision comes to the rescue: an expression like Thing{100}
no longer creates an object but merely specifies how some other object (your array element) is to be created.
C++11 array initialization with a non-copyable type with explicit constructor
-
29-06-2023 - |
Domanda
I have a (third-party) class which is non-copyable. I'd like to initialize an array of them. Here's my best attempt:
#include <array>
class Thing
{
public:
explicit Thing(int) {}
Thing(const Thing&) = delete;
};
int main()
{
std::array<Thing, 1> things{{{100}}}; // error here
};
GCC 4.7.2 says:
error: converting to ‘std::array::value_type {aka Thing}’ from initializer list would use explicit constructor ‘Thing::Thing(int)’
OK, but that's exactly what I want--to use the explicit constructor. How can I express that? If I actually invoke the constructor myself, then I get an error about the copy constructor being deleted. And I can't use std::move()
because Thing is not movable (and I can't modify it).
The only alternative I've found so far is https://stackoverflow.com/a/15962814/4323 but this is undesirable because it's a bunch of extra code plus I need to cast the "storage" everywhere I use it (or keep a separate pointer to it, which adds indirection I don't want).
I want a solution that gives maximum performance when actually using the Things without a lot of ugly boilerplate.
Soluzione
Altri suggerimenti
I tried adding the default move ctor and move assignment operator, changed the initialization a bit and it compiles:
#include <array>
class Thing
{
public:
explicit Thing(int) {}
Thing(const Thing&) = delete;
Thing(Thing&&) = default;
Thing& operator=(Thing&&) = default;
};
int main()
{
std::array<Thing, 1> things {{ Thing(100) }}; // error gone
}
EDIT: I'd missed the "third-party" part. Sorry if this doesn't help :)
You can use a std::vector
:
std::vector<Thing> things;
things.reserve(1);
things.emplace_back(100);
or for just one element boost::optional
:
boost::optional<Thing> thing;
thing.emplace(100);