Le 9 oct. 2014 à 12:35, Joaquin M Lopez Munoz <joaquin@tid.es> a écrit :
I think you forgot to add that support in some of poly_older ctors and assignment operators:
poly_holder(const poly_holder& x); poly_holder& operator=(const poly_holder& x); poly_holder& operator=(poly_holder&& x);
Yes, thanks. I wanted to try another approach: one factory per node type. Here is a version that seems to work, but does not use Boost.Flyweight at all. Instead each node type maintains the factory as a plain std::map<tuple<Arguments>, weak_ptr<Value>>. This is a weak_ptr otherwise if I store shared_ptr, then of course the values are kept alive by the factory itself. This is the result: http://coliru.stacked-crooked.com/a/28bb07a0b0e59fbb For instance Bin reads: struct Bin_impl; using Bin = std::shared_ptr<Bin_impl>; struct Bin_impl: Exp_impl { // cannot make it private: we need friendship with // std::make_shared<Bin_impl>'s internal details, which seems // impossible to spell out portably. Bin_impl(char o, Exp lhs, Exp rhs) : op(o) , l(lhs) , r(rhs) {} public: ~Bin_impl() {} static Bin make(char o, Exp lhs, Exp rhs) { static std::map<std::tuple<char, Exp, Exp>, std::weak_ptr<Bin_impl>> map_; auto k = std::make_tuple(o, lhs, rhs); auto i = map_.find(k); if (i == end(map_) || i->second.expired()) { auto res = std::make_shared<Bin_impl>(o, lhs, rhs); map_.emplace(k, res); return res; } else return Bin(i->second); } ... Which is ok. However, I tried to do the same thing this time on top of Flyweight, using key_value, but failed miserably: the result is not made unique: http://coliru.stacked-crooked.com/a/2b768fa26574adea I tried this way: struct Num_impl; using Num = std::shared_ptr<const Num_impl>; std::ostream& operator<<(std::ostream& o, const Num_impl& b); struct Num_impl { //private: Num_impl(int v) : val(v) { std::cerr << '!' << *this << '\n'; } ~Num_impl() { std::cerr << "~" << *this << '\n'; } struct make_num : boost::noncopyable { make_num(int n) : res(std::make_shared<Num_impl>(n)) {} Num res; operator Num() const { return res; } }; public: static Num make(int v) { using flyweight = boost::flyweight<boost::flyweights::key_value<int,make_num>>; return flyweight(v).get(); } std::ostream& print(std::ostream& o) const { return o << val; } int val = 0; }; I suppose that it's a bad idea for Num::make to return the result of the call to get(), as this prevents the flyweight from tracking the values. Yet the destructor was not called, so I don't understand why Flyweight fails to see the duplicate 42.