лупхолы или нет? Можно ли будет узнать с какими типами проинстанциировалась функция/метод? Это очень нужно для стирания типа - то есть шаблонная функция в одном месте стирает тип а потом мы хотим в отдельном месте пройтись по этим типам с которым была проинстанциирована эта функция чтобы сделать проверку на рантайм-айдишник у объекта таким образом получив статический тип в лямбда-коллбеке
Например вот есть такая обертка ErasedType которая стирает тип
struct A {
....
}
struct B {
...
}
struct ErasedType {
void* ptr;
int typeId
ErasedType(auto obj){
ptr = obj;
typeId = GetUniqueIdForType<decltype(obj>()
}
}
и используем ее когда хотим например вернуть объекты разного типа из функции или добавить в какой-то контейнер
ErasedType getObj(){
if(rand() % 2){
return new A{};
} else {
return new B{};
}
}
но дальше в другом месте программы нам нужно получить статический тип и тут нужен способ пройтись по типам с которыми был проинстанциирован шаблонный конструктор ErasedType чтобы заматчить рантайм-тип (по сохраненному айдишнику) и в случае совпадания вызывать лямбду
auto getStaticType(ErasedType obj, auto fn){
//здесь нужен список типов T1, T2, T3, ... с которым был проинстанциирован конструктор ErasedType чтобы дальше заматичить айдишник и вызывать лямбду с конкретным типом после каста
if(GetUniqueIdForType<T1>() == obj.id){
fn(static_cast<T1>(obj.ptr);
}
if(GetUniqueIdForType<T2>() == obj.id){
fn(static_cast<T2>(obj.ptr);
}
if(GetUniqueIdForType<T3>() == obj.id){
fn(static_cast<T3>(obj.ptr);
}
...
}
ErasedType obj = getObj();
getStaticType(obj, [](auto concreteObj){
//здесь получаем уже статический тип
})
Да, можно будет делать всё что угодно! P.S.: А чем std::variant не подошёл для это примера?
Интересно, как a.cpp узнает про инстанцирования из b.cpp
с std::variant нужно заранее знать типы, а как я заранее узнаю тип для лямбды? что если я возвращаю по рантайм-if-у из функции или добавляю в контейнер разные лямбды (с разными замыкаемыми переменными) ?
Вроде std::function поможет с лямбдами
а как в std::function засунуть шаблонную лямбду?
ИМХО без динамических аллокаций красивее получается: std::variant<A, B> getObj(){ if(rand() % 2){ return A{}; } else { return B{}; } }
А как именно выглядит решаемая вами задача? Интересно как вы потом type_erased лямбду в другой единице трансляции в правильгый тип кастите
ну логично что сейчас лупхолы ограничены одной единицей трансляции но через лупхолы пример выше решается так https://godbolt.org/z/7hWfx18qd
Суть не в динамических аллокациях, суть в том что с std::variant нужно заранее знать типы а пример с лупхолами этого не требует
а рефлексия каким образом должна помочь протянуть тентакли за пределы единицы трансляции?
в общем я правильно понимаю что сейчас в С++ нет никаких способов реализовать аналог std::function для шаблонных лямбд, кроме костыльных лупхолов?
Красота... А если к std::any добавить функцию visit, ваши цели это покроет?
а это вообще реально?
а как это будет реализовано?
Наверняка... Надо только придумать как :)
В общем народ, я тут профиксил один баг и немного отрефактрил и вот мой контрибушн сообществу - https://github.com/vampyrofangclub/horrifiction - маленькая библиотека которая предоставляет два хелпера для реализации своих type-erasure any-like оберток template <typename T> constexpr int __get_id_from_type(); constexpr bool __get_type_from_id_impl(int typeId, void* ptr, auto fn); первая функция по переданному типу возвращает уникальный int-айдишник для типа, например __get_id_from_type<int>() //0 __get_id_from_type<double>() //1 struct SomeStruct {...} __get_id_from_type<SomeStruct>() //2 auto someLambda = [](auto anotherLambda){ return anotherLambda(123); } __get_id_from_type<decltype(someLambda)>() //3 а вторая функция делает наоборот - мы передаем int-айдишник типа (полученный из первой функции) и void* указатель и также шаблонную лямбда-коллбек и функция вызовет этот лямбда-коллбек и передаст этот void*-указатель закастованный в соотвествующий тип (и возвращает bool-флаг прошел ли матчинг - например false если матчинг не прошел и лямбда-коллбек не был вызван) void* myObjPtr = myObj; int myObjTypeId = __get_id_from_type<decltype(myObj)>(); __get_type_from_id(myObjTypeId, myObjPtr, [](auto myObj){ std::cout << "myObj->value:" << myObj->value << "\n"; }); другие примеры (простой Any-враппер для сохранения в контейнере объектов разных типов а также для возврата из функции разных шаблонных лямбд) можно посмотреть тут - https://godbolt.org/z/6GfqE3bes
почему?
https://en.cppreference.com/w/c/language/identifier#:~:text=All%20identifiers%20that%20begin%20with%20an%20underscore%20followed%20by%20a%20capital%20letter%20or%20by%20another%20underscore
понял, пойду переименую)
В конце имена - можно
Обсуждают сегодня