Opened 7 years ago

Last modified 7 years ago

#11276 new Bugs

Ability to hold already type erased object into a type erased reference.

Reported by: germandiago Owned by: Steven Watanabe
Milestone: To Be Determined Component: type_erasure
Version: Boost 1.55.0 Severity: Problem
Keywords: Cc:

Description

I would like to ask for an enhancement to this fantastic library, that is making me so happy in the absence of non-library solutions in c++ :)

This problem came up in my code:

class my_concept :  public any<requirements> {
   using base = any<requirements>;
public:
   using base::base;
};

class my_concept_ref : public any<requirements, _self &> {
   using base = any<requirements, _self&>;
public:
   template <class... Args>
   my_concept_ref(Args &&... args) : base(std::forward<Args>(args)...) {}
};

//client code
vector<my_concept> vec;
//
vec.push_back(my_concrete_model{});

my_concept_ref get_a_type_erased_type_in_a_ref(vector<my_concept> & vec) {
    return vec[0];
}

//Throws bad_cast:
auto & want_my_model = any_cast<my_concrete_model&>(get_a_type_erased_type_in_a_ref());

//I must do this:
auto & will_give_me_my_model = any_cast<my_concrete_model&>(any_cast<my_concept &>(
  get_a_type_erased_type_in_a_ref());

The problem here is that when the constructor for my_concept_ref takes an already type erased type from the vector (my_concept), it wraps that concrete type, which is a model of my_concept, but it was already type_erased, and not the internal concrete model (my_concrete_model).

What could be implemented is automatic unwrapping of a type erased type so that I can do this:

//Throws bad_cast:
auto & want_my_model = any_cast<my_concrete_model&>(get_a_type_erased_type_in_a_ref());

I think this should work. There is no easy workaround but to cast twice. I think the runtime concept constructor should check wether the class being taking in the constructor is actually already a type erased one based on detecting any<requirements>. I do not want to use in my code both my_concept & and my_concept_ref depending on wether I wrapped my concrete class or not in a type erased wrapper. This would give the library more uniformity and makes sense conceptually, because my_concept & can only be used in case I wrapped my type in a my_concept &, which is not always the case.

Great work, by the way! I am trying to make heavy use of the library and so far it is serving me very well.

Change History (2)

comment:1 by Steven Watanabe, 7 years ago

Is there a good reason that you need to inherit from any instead of just using a typedef? Your example will work with any<C, _self> and any<C, _self&>. If you really need to create your own wrapper, then you need to define the extra constructor overloads needed to make it work.

in reply to:  1 comment:2 by anonymous, 7 years ago

Replying to steven_watanabe:

Is there a good reason that you need to inherit from any instead of just using a typedef? Your example will work with any<C, _self> and any<C, _self&>. If you really need to create your own wrapper, then you need to define the extra constructor overloads needed to make it work.

The ability to forward declare my types is important. With typedef and using this is not possible.

Note: See TracTickets for help on using tickets.