问题
Below is an example program where a 'Container' class needs to store a list of 'Items' via a base class pointer. Having started with C++11/14 the natural choice would be to use std::unique_ptr and variadic templates in the case I have.
However being new I cannot fathom how to convert the variadic list into and initialiser list for the vector of unique_ptr in a manner that compiles. Help is greatly appreciated as I have failed to find anything online that helps me with this issue so far (albeit likely out there!).
Thanks in advance:
// Example program
#include <iostream>
#include <string>
#include <memory>
#include <vector>
struct Item
{
};
struct Container
{
template<typename... Items>
Container( Items&&... items )
: items_( {std::make_unique<Items>(items)...} ) //<<TODO: How, VC compiler times out with this code!?
{
}
std::vector<std::unique_ptr<Item>> items_;
};
struct A : Item { A(float){} };
struct B : Item { };
struct C : B { C(float){} };
struct D : Item { D(float){} };
int main()
{
Container x( A(1), C(2), D(3) );
return 0;
}
回答1:
The issue is that you cannot move unique_ptr
out from intializer_list
. Read this question for more details.
This solution use the technique in this answer that instead of using intializer_list
, you can use plain array to construct items.
struct Container
{
template<typename... Items>
Container( Items&&... items )
: items_()
{
std::unique_ptr<Item> itemArr[] = {std::make_unique<Items>(std::move(items))...};
items_ = std::vector<std::unique_ptr<Item>> {std::make_move_iterator(std::begin(itemArr)), std::make_move_iterator(std::end(itemArr))};
}
std::vector<std::unique_ptr<Item>> items_;
};
Online Demo
来源:https://stackoverflow.com/questions/33747131/variadic-construction-for-initialising-vector-of-unique-ptr-to-base-type