I'm trying to allocate an array of objects that are neither copy constructible, assignable nor has a default constructor. The objects have arguments that are determined at run time. I know that you can solve this problem by having an array of pointers or cleverly using placement new but I'm more interested in if this is possible to do cleanly with C++11 (1y) magic. So please, this is purely of theoretical interest so avoid trying to solve "my problem" by offering a work around.
...So the question is: Is there a way to make the following work in C++11 or C++14:
class X{
public:
explicit X(int a){...}
X(const X&) = delete;
void operator = (const X&) = delete;
private:
...
};
class Y{
public:
Y(const std::vector<int>& args) {
x = new X[]{args};
}
~Y(){
delete [] x;
}
private:
X* x;
};
Specifically I'm looking for a solution/construct that meets the following criteria:
I forgot to mention that move constructor is not available. In the actual case at hand, X spawns a worker thread and is executing in the context of this of the initially constructed object, any attempt to use a move constructor will corrupt the state of the executing thread.
You can use std::vector and its emplace_back function if you make X at least movable.
class X{
public:
explicit X(int){}
X(X&&) = default;
X(const X&) = delete;
void operator = (const X&) = delete;
};
int main() {
std::vector<X> xs;
xs.emplace_back(0);
xs.emplace_back(1);
xs.emplace_back(2);
xs.emplace_back(3);
}
(If you declare a copy constructor, even if that declaration deletes it, the compiler will not automatically generate any special move member, so you need to explicitly request them)
This basically boils down to the "array with placement new" strategy, but all abstracted away into high-level notions.
If you cannot make use of a movable type, you have to implement a vector-like class that pre-allocates storage and never reallocates. There is nothing similar in the standard library.
You're going to have to keep track of the constructed elements by hand, but you can use allocator to help:
class Y{
public:
Y(const std::vector<int>& args):
alloc{},
n{args.size()},
x{alloc.allocate(n)}
{
auto end = x;
try {
for (auto arg: args)
alloc.construct(end++, arg);
} catch (...) {
while (end != x)
alloc.destroy(--end);
alloc.deallocate(x, n);
throw;
}
}
~Y() {
for (auto end = std::next(x, n); end != x; --end)
alloc.destroy(end);
alloc.deallocate(x, n);
}
private:
std::allocator<X> alloc;
const std::size_t n;
const X *x;
};
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