|
Boost Users : |
Subject: Re: [Boost-users] Flyweight: wrapping shared_ptr
From: Akim Demaille (akim_at_[hidden])
Date: 2014-10-09 11:29:02
Le 9 oct. 2014 à 12:35, Joaquin M Lopez Munoz <joaquin_at_[hidden]> 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.
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net