I would like to have a type that is just a list of objects that may be derived off some base class. That is, the caller gets a list of Stuff
or MoreStuff
(which is derived from Stuff
), and can operate on at least the Stuff parts.
This sounds like std::vector< std::unique_ptr< Stuff > >
to me. However, I also want to initialise it with the brace initializer, and this is where I'm drawing a blank.
This is more or less what I'm attempting:
#include <vector>
#include <memory>
#include <string>
struct Stuff {
std::string s1;
std::string s2;
};
using AllStuff = std::vector< std::unique_ptr< Stuff > >;
AllStuff const MyStuff = {
std::make_unique<Stuff>( Stuff{"1", "one"} )
};
struct MoreStuff : public Stuff {
std::string s3;
};
AllStuff const AllMoreStuff = {
std::make_unique<Stuff>( MoreStuff{"2", "two", "too"} )
};
Or, rather, something like that. The less typing (for adding more Stuff
to the vector) the better.
The theory would be that there would be a method that would take a reference to either AllStuff
or AllMoreStuff
as the parameter, and be able to use s1
and s2
from it. Other methods would only take AllMoreStuff
and be able to use s3
(through an appropriate use of dynamic_cast<MoreStuff*>(...)
).
However, the theory and reality aren't quite lining up yet, and any help in determining how to brace-initialise a list of derived objects would be appreciated.
You can't use std::initializer_list
with std::unique_ptr
as std::unique_ptr
is noncopyable and initialization with std::initializer_list
implies copying.
You could probably switch to std::shared_ptr
and add constructors to your structs:
struct Stuff {
Stuff(const std::string& s1, const std::string& s2)
: s1(s1)
, s2(s2)
{}
std::string s1;
std::string s2;
};
using AllStuff = std::vector< std::shared_ptr< Stuff > >;
AllStuff const MyStuff = {
std::make_shared<Stuff>("1", "one")
};
struct MoreStuff : Stuff {
MoreStuff(const std::string& s1, const std::string& s2, const std::string& s3)
: Stuff(s1, s2)
, s3(s3)
{}
std::string s3;
};
AllStuff const AllMoreStuff = {
std::make_shared<MoreStuff>("2", "two", "too")
};