Initialization of C ++ 11 array with non-convertible type with explicit constructor

I have a (third-party) class that is not being copied. I would like to initialize an array of them. Here is 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: conversion to 'std :: array :: value_type {aka Thing} from the list of initializers will use the explicit constructor "Thing :: Thing (intermediate)

OK, but this is exactly what I want - to use an explicit constructor. How can I put it? If I call the constructor myself, then I get an error message about deleting the copy constructor. And I cannot use std::move() because Thing is not moving (and I cannot change it).

The only alternative that I have found so far is https://stackoverflow.com/a/4122166/212 , but this is undesirable because it is a bunch of extra code plus I need to drop the β€œrepository”, I use it everywhere (or keep a separate pointer on him, which adds an indirection that I don't want).

I want a solution that gives maximum performance when actually using Things without a lot of ugly template.

+7
c ++ arrays initialization c ++ 11 noncopyable
source share
3 answers

Again, C ++ 17 guaranteed elision copying comes to the rescue: an expression like Thing{100} no longer creates an object, but simply indicates how some other object should be created (your array element).

+1
source share

I tried adding the default ctor move and moving the assignment operator, slightly changed the initialization, and compiled:

 #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 missed the "third party" part. Sorry if this does not help :)

+1
source share

You can use std::vector :

 std::vector<Thing> things; things.reserve(1); things.emplace_back(100); 

or for just one boost::optional element:

 boost::optional<Thing> thing; thing.emplace(100); 
-2
source share

All Articles