Le 9 oct. 2014 à 12:35, Joaquin M Lopez Munoz 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. 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;
struct Bin_impl: Exp_impl
{
// cannot make it private: we need friendship with
// std::make_shared'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::weak_ptr> 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(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(n))
{}
Num res;
operator Num() const { return res; }
};
public:
static Num make(int v)
{
using flyweight =
boost::flyweight>;
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.