Initializing container of unique_ptrs from initializer list fails with GCC 4.7
unique_ptr
's constructor is explicit
. So you can't create one implicitly with from new string{"foo"}
. It needs to be something like unique_ptr<string>{ new string{"foo"} }
.
Which leads us to this
// not good
vector<unique_ptr<string>> vs {
unique_ptr<string>{ new string{"Doug"} },
unique_ptr<string>{ new string{"Adams"} }
};
However it may leak if one of the constructors fails. It's safer to use make_unique
:
// does not work
vector<unique_ptr<string>> vs {
make_unique<string>("Doug"),
make_unique<string>("Adams")
};
But... initializer_list
s always perform copies, and unique_ptr
s are not copyable. This is something really annoying about initializer lists. You can hack around it, or fallback to initialization with calls to emplace_back
.
If you're actually managing string
s with smart pointers and it's not just for the example, then you can do even better: just make a vector<string>
. The std::string
already handles the resources it uses.
How to initialize a container of noncopyable with initializer list?
You can't move objects out of initializer lists, since they only allow const access to their members. As such, you can't use initializer lists and move constructors; they can only be copied.
Moving unique_ptr in the declaration of a vector
When you do
vector<unique_ptr<int>> v2 {move(i1), move(i2), move(i3)};
you are not actually moving directly into the vector v2
. Instead the compiler will create a std::initializer_list
of the moved unique pointers, and pass that list object to the std::vector
constructor which will then attempt to copy the elements from the initializer list.
Unfortunately I know of no way to solve the problem, of using the intermediate initializer list to initialize a vector of unique pointers.
How to fix vector of objects that have unique_ptr
The root cause of the error I was getting is due to use of unique_ptr
inside the object that is used in intializer list. Similar to vector of simple unique_ptr
(as in here Initializing container of unique_ptrs from initializer list fails with GCC 4.7 ) an object that also has unique_ptr
in its data model can also NOT be used in initializer list.
Similar to the other link, cause is same; initializer list always performs copies and unique_ptr
cannot be copied. So we have to use emplace_back
/push_back
.
So even with constructor in place the following solution works
struct Container
{
struct Nested{
std::unique_ptr<Container> node;
Nested(): node(nullptr) {}
Nested(std::unique_ptr<Container> t) : node(std::move(t)) {}
};
std::vector<Nested> edges;
};
typedef std::unique_ptr<Container> UCont;
typedef Container::Nested Nested;
int main()
{
auto v = std::vector<Nested>{3};
v.push_back(std::move(Nested(std::move(std::unique_ptr<Container>(new Container{})))));
v.push_back(std::move(Nested(std::move(std::unique_ptr<Container>(new Container{})))));
v.push_back(std::move(Nested(std::move(std::unique_ptr<Container>(new Container{})))));
std::unique_ptr<Container> object = UCont(new Container { std::move(v) });
}
How do you initialize (through initializer lists) a multidimensional std::array in C++11?
Try to add one more pair {}
to ensure we're initializing the internal C array.
std::array<std::array<int, 2>, 2> shape = {{ {1, 1},
{1, 1} }};
Or just drop all the brackets.
std::array<std::array<int, 2>, 2> shape = { 1, 1,
1, 1 };
Meaning of error converting brace enclosed initializer list to type?
The correct syntax is:
timed_mutex() : _M_mutex({__GTHREAD_MUTEX_INIT}) { } // i.e. _M_mutex({{0}})
However that feature is available only with C++11. Demo.
For older compilers, you can't use initializer list with constructor.
The reason for having 2 {}
is that, pthread_mutex_t
is a union
defined as shown here. Which contains, a struct
, char[24]
, long int
; thus naturally the initialization syntax would differ.
Update:
When I tried to compile <mutex>
header in a test file, it gives following error:
/usr/include/c++/4.6/bits/c++0x_warning.h:32:2: error: #error This
file requires compiler and library support for the upcoming ISO C++
standard, C++0x. This support is currently experimental, and must be
enabled with the -std=c++0x or -std=gnu++0x compiler options.
Quite possibly the particular file follows the initializer syntax of C++11.
Can I list-initialize a vector of move-only type?
The synopsis of <initializer_list>
in 18.9 makes it reasonably clear that elements of an initializer list are always passed via const-reference. Unfortunately, there does not appear to be any way of using move-semantic in initializer list elements in the current revision of the language.
Specifically, we have:
typedef const E& reference;
typedef const E& const_reference;
typedef const E* iterator;
typedef const E* const_iterator;
const E* begin() const noexcept; // first element
const E* end() const noexcept; // one past the last element
Initializing simple structs using initializer lists with clang
That is a bug in clang++:
http://llvm.org/bugs/show_bug.cgi?id=12670
In your case you can just use the explicit call to the constructor, as you provide in the last code snippet. As of whether the semantics are really the same (will it generate the same code), in most cases it will.
The case where the different syntax will lead to different behavior is when the type being constructed has a constructor that takes a std::initializer_list<>
, in which case the brace-initializer will construct that initializer list. If the type does not have such a constructor, as is your case, the brace-initializer will call the appropriate constructor.
Related Topics
What Does 'Return *This' Mean in C++
Why Must Std::Sort Compare Function Return False When Arguments Are Equal
Creating a Thread Pool Using Boost
Lambda Capture and Parameter with Same Name - Who Shadows the Other? (Clang VS Gcc)
How to Resize a 2D Vector of Objects Given the Width and Height
True Isometric Projection with Opengl
How to Execute Another Exe from a C++ Program in Windows
Gui Toolkits, Which Should I Use
Lto, Devirtualization, and Virtual Tables
Qtcpsocket: Reading and Writing
How to Load a Custom Binary Resource in a Vc++ Static Library as Part of a Dll
Validate Authenticode Signature on Exe - C++ Without Capicom
Why Was Std::Strstream Deprecated
Std::Forward_List and Std::Forward_List::Push_Back
How to Expand an Array Dynamically in C++? {Like in Vector }
What Are Uses of the C++ Construct "Placement New"
How to Avoid Undefined Execution Order for the Constructors When Using Std::Make_Tuple