You can use Boost.Variant instead of pointers in your container. This avoids many environmental and memory management issues. In addition, you get a lot more from the default constructors.
Here is a complete redistribution of your example using this design:
#include <vector> #include <iterator> #include <string> #include <boost/variant.hpp> struct Foo { Foo() : m_x("abc") {} std::string m_x; }; struct FooDerivedA : Foo { FooDerivedA() : m_y(123) {} int m_y; }; struct FooDerivedB : Foo { FooDerivedB() : m_z(true) {} bool m_z; }; typedef boost::variant<FooDerivedA, FooDerivedB> a_foo; struct to_string : boost::static_visitor<std::string> { std::string operator()(Foo const& foo) const {return foo.m_x;} std::string operator()(FooDerivedA const& foo) const {return foo.m_x + ", " + std::to_string(foo.m_y);} std::string operator()(FooDerivedB const& foo) const {return foo.m_x + ", " + std::to_string(foo.m_z);} }; std::ostream& operator<<(std::ostream& os, a_foo const& foo) { return os << boost::apply_visitor(to_string(), foo); } int main() { std::vector<a_foo> f1; f1.push_back(FooDerivedA()); f1.push_back(FooDerivedB()); auto f2 = f1; std::ostream_iterator<a_foo> out_it(std::cout, "\n"); std::cout << "f1:" << std::endl; std::copy(f1.begin(), f1.end(), out_it); std::cout << "f2:" << std::endl; std::copy(f2.begin(), f2.end(), out_it); return 0; }
source share