Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top