Nikita
ребята, у меня есть функция которая генерирует лямбды
Nikita
есть ли способ при каждом вызове генерить лямбду нового класса?
Nikita
типо чтобы у всех лямбд различался тип
Sheridan
Эм... Может и мне так надо... Зачем?
Nikita
мне нужно создать вектор, тип которого я узнаю только в момент вызова лямбды))))
Nikita
хотел написать аля [](auto &&v) {
static std::vector<decltype(v)> vec;
}
Nikita
фигня в том, что вектор будет один и тот же для разных инстансов лямбд
Nikita
получается какой то type erasure на стероидах
Anonymous
А в среднем за урок что успевал?
Anatoly
Nikita
мне по рукам надают за лишние аллокации((
Alexander "SonnySlave"
Nikita
если я отвечу, то вы меня отправите в supapro)))
Nikita
всмысле я стараюсь этого избежать наоборот
Nikita
или я не понял вопроса
Anatoly
так ты хочешь от этого уйти?
Nikita
да
Nikita
ещё раз
Nikita
сейчас накидаю код
Anatoly
давай лучше начни с задачи
Anatoly
а то xy проблемой попахивает
Nikita
В общем, мне нужно создать функтор, который будет скапливать в себе объекты до момента, пока их не окажется определённое количество. Потом выплёвывает все эти элементы
Nikita
интерфейс std::optional<std::vector<T>>(T &&)
Александр
Nikita
T узнаётся только в момент вызова
Alexander "SonnySlave"
что значит только в момент вызова? Все типы известны в compile-time
Alexander "SonnySlave"
я обращаю внимание - типы, а не то, что лежит по ссылке\указателю(я опускаю полиморфизм всякий)
Nikita
я имею в виду оператор() должен быть шаблонный
Nikita
именно оператор() а не тип функтора
Alexander "SonnySlave"
ну так инстанциация шаблона известна на этапе компиляции....
Nikita
т.е. неканает template<typename T>
struct MyFunctor
Nikita
где хранить вектор?
Alexander "SonnySlave"
в рифмЕ
Nikita
а если серьёзно? как поле класса не получится, ибо я не знаю тип
Assasin
тип не T?
Nikita
ща
Assasin
а, НЕ канает
Nikita
тип T шаблонный
Anatoly
тип T шаблонный
напиши, как ты представляешь код, который будет использовать этот функтор
Anatoly
f(10.0);
f(std::string("hello");
f(10);
f(false);
Anatoly
?
Anatoly
и для каждого типа у тебя отдельный вектор значений?
Nikita
т.е. примерно должно быть так
struct MyFunctor
{
template<typename T>
std::optional<std::vector<T>> operator(T &&value)
{
//допустим мы создали где то вектор с именем vec
vec.emplace_back(value);
if (vec.size() == 10)
{
return std::move(vec);
}
return std::nullopt;
}
};
Nikita
ой
Nikita
чё то с выравниванием
Alexander "SonnySlave"
Anatoly
пока нет
Assasin
в векторе нельзя хранить элементы разных типов, если я правильно понял, о чем ты
Nikita
не не
Nikita
посмотрите на код функтора
Nikita
вопрос в том где создать vec
Assasin
а если T всегда будет один и тот же между вызовами, то чем не подходит шаблонная структура?
Nikita
в том, что я это T заранее не знаю, соответственно не смогу создать инстанс такой структуры
Александр
Assasin
ну значит сделай место использования тоже шаблоном и подставляй T
Александр
Для надёжности можно thread_local
Assasin
статический не позволит несколько инстансов функтора делать разных же, с одним и тем же типом
Nikita
Александр
Тогда предлагаю создать статический std::map<MyFunctor*, std::vector<T>>
Nikita
о
Assasin
жесть, конечно, выглядит как костыль)
Nikita
ах да, ещё одна особенность, максимальный размер вектора я знаю до вызова operator()
Assasin
я бы так не стал делать, это еще и на производительности скажется из-за поиска по карте, и по памяти оверхед
Nikita
ну т.е. размер, до которого копить надо
Nikita
впринципе можно хранить void*
Nikita
и кастовать его
Assasin
т.е. vector<int> уже не получится
Nikita
ага, понял сейчас
Anatoly
+
у разных инстансов этой структуры вектор будет один и тот же
struct foo {
template <typename T> auto add(T &&e) {
static std::vector<T> v;
v.emplace_back(std::forward<T>(e));
if (v.size() == 2) {
return std::optional<std::vector<T>>(std::move(v));
}
return std::optional<std::vector<T>>();
}
};
TEST(misc, foo) {
foo f;
ASSERT_EQ(std::optional<std::vector<double>>(), f.add(10.0));
ASSERT_EQ(std::optional<std::vector<double>>({10.0, 20.0}), f.add(20.0));
ASSERT_EQ(std::optional<std::vector<int>>(), f.add(100));
ASSERT_EQ(std::optional<std::vector<int>>({100, 200}), f.add(200));
}
Anatoly
а если нужна лямбда используй этот вспомогательный foo
Assasin
так ему ж наоборот не нужно, чтобы вектор был общий у разных инстансов
Nikita
у разных инстансов foo будет один и тот же вектор при одном и том же T
Anatoly
а как нужно?
Nikita
Nikita
чтоб были разные
Anatoly
каков критерий создания разных сущностей для одинакового типа?