Why can't I return a unique_ptr
from a clone
function? I thought I could do this.
I have a base class for different mathematical functions called transform
. I have a container of pointers to this type because I am using polymorphism. For example, all these derived classes have a different implementation of log_jacobian
that is useful for statistical algorithms.
I am using unique_ptr
s to this transform
class, and so I have made a (pure virtual) clone
function that makes new unique_ptr
pointing to a deep copy of the same mathematical transform
object. This new object is of the same type that derives from transform<float_t>
, but it's a separate because you can't have two unique_ptr
s pointing to the same thing.
template<typename float_t>
class transform{
...
virtual std::unique_ptr<transform<float_t>> clone() const = 0;
...
};
My transform_container
class holds a few of these at a time. After all, most statistical models have more than one parameter.
template<typename float_t, size_t numelem>
class transform_container{
private:
using array_ptrs = std::array<std::unique_ptr<transform<float_t>>, numelem>;
array_ptrs m_ts;
unsigned m_add_idx;
...
auto get_transforms() const -> array_ptrs;
};
I'm not sure why the deep copy function get_transforms
isn't working, though. It is used to make copies, and to access individual transformations from the container. I get a segfault when I run some tests. If I run it in gdb
, it explicitly tells me the line with a comment after it is bad.
template<typename float_t, size_t numelem>
auto transform_container<float_t,numelem>::get_transforms() const -> array_ptrs
{
array_ptrs deep_cpy;
for(size_t i = 0; i < numelem; ++i){
deep_cpy[i] = m_ts[i]->clone(); // this line
}
return deep_cpy;
}
I've also tried std::move
ing it into deep_cpy[i]
and using unique_ptr::reset
, but to no avail.
Edit:
here are some other relevant methods: a method that adds transforms to transform_container
, and the factory method for the individual transform
:
template<typename float_t>
std::unique_ptr<transform<float_t> > transform<float_t>::create(trans_type tt)
{
if(tt == trans_type::TT_null){
return std::unique_ptr<transform<float_t> >(new null_trans<float_t> );
}else if(tt == trans_type::TT_twice_fisher){
return std::unique_ptr<transform<float_t> >(new twice_fisher_trans<float_t> );
}else if(tt == trans_type::TT_logit){
return std::unique_ptr<transform<float_t> >(new logit_trans<float_t> );
}else if(tt == trans_type::TT_log){
return std::unique_ptr<transform<float_t> >(new log_trans<float_t> );
}else{
throw std::invalid_argument("that transform type was not accounted for");
}
}
template<typename float_t, size_t numelem>
void transform_container<float_t, numelem>::add_transform(trans_type tt)
{
m_ts[m_add_idx] = transform<float_t>::create(tt);
m_add_idx++;
}
Aucun commentaire:
Enregistrer un commentaire