Итак, предположим, что я хочу набрать стирание с помощью стирания типа.
Я могу создавать псевдо-методы для вариантов, которые позволяют естественное:
pseudo_method print = [](auto&& self, auto&& os){ os << self; };
std::variant<A,B,C> var = // create a variant of type A B or C
(var->*print)(std::cout); // print it out without knowing what it is
Мой вопрос в том, как я могу распространить это на std::any
?
Это невозможно сделать "в сыром". Но в точке, где мы назначаем/строим a std::any
, мы имеем информацию о типе, которая нам нужна.
Итак, теоретически расширенный any
:
template<class...OperationsToTypeErase>
struct super_any {
std::any data;
// or some transformation of OperationsToTypeErase?
std::tuple<OperationsToTypeErase...> operations;
// ?? what for ctor/assign/etc?
};
может каким-то образом автоматически перепрограммировать некоторый код, чтобы работа над этим типом синтаксиса работала.
В идеале это было бы столь же кратким в использовании, как вариант.
template<class...Ops, class Op,
// SFINAE filter that an op matches:
std::enable_if_t< std::disjunction< std::is_same<Ops, Op>... >{}, int>* =nullptr
>
decltype(auto) operator->*( super_any<Ops...>& a, any_method<Op> ) {
return std::get<Op>(a.operations)(a.data);
}
Теперь я могу сохранить это в типе, но разумно использовать синтаксис лямбда, чтобы все было просто?
В идеале хочу:
any_method<void(std::ostream&)> print =
[](auto&& self, auto&& os){ os << self; };
using printable_any = make_super_any<&print>;
printable_any bob = 7; // sets up the printing data attached to the any
int main() {
(bob->*print)(std::cout); // prints 7
bob = 3.14159;
(bob->*print)(std::cout); // prints 3.14159
}
или аналогичный синтаксис. Это невозможно? Неосуществимым? Легко?