Задать вопрос
  • Какой контейнер выбрать для поиска по ключу для разных размеров?

    Dyikot
    @Dyikot Автор вопроса
    Евгений Шатунов, По ответу rPman я решил одну задачу перенести с unordered map на vector, где ключ индекс а другие оставить как есть. Но опять же когда какие использывать знаю. Тут был вопрос на сколько правдивы эти графики просто. Просто я всегда считал что хеш таблица должна быть быстрее находить по ключу на любом числе данных, не думая о кеше и после этого видео возникли сомнения. Ведь у меня много небольших unordered_map. Очевидно где мне нужно будет производить не только поиск но и итерировать контейнер, либо мне нужны сортированные данные тогда я просто возьму тот же map или flat_map.
    Написано
  • Какой контейнер выбрать для поиска по ключу для разных размеров?

    Dyikot
    @Dyikot Автор вопроса
    Евгений Шатунов, Интересный опрос. Про deque не скажу, т.к не пользовался. vector динамический массив, память непрерывна, произвольный доступ. list по сути представлет собой несколько структур пусть называются они node, в которой указатели на следующий и предыдущий и значение. map вроде схожа на лист(в плане тоже есть node) только они предсталены в виде дерева и в нем производится двоичный поиск. unordered_map особо не вникал как что там. Но вроде представлется вектор листов? по крайнер мере стандратная реализация. Гланое что я передаю ключ он хешируется через std hash и я получаю нужное мне значение.

    Из стандартных пользуюсь только vector, unordered_map, queue, редко stack. Ну и сделал отдельно SortedVector.
    Написано
  • Почему function wrapper с ссылкой в сигнатуре может принимать pointer to member function?

    Dyikot
    @Dyikot Автор вопроса
    Евгений Шатунов, Почему это не должно работать на других компиляторах? И причем тут настройки компилятора? Это может не работать если в реализации делегата не будет соответсвенной проверки типа и соотвенно правильного вызова указателя на метод. Если на cppreference про стандарный делегат есть соответсующее описание что это поддерживается то тогда я считаю что это стандарт.
    Instances of std::function can store, copy, and invoke any CopyConstructible Callable target -- functions (via pointers thereto), lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

    А почему и ссылку и указатель принимает я уже понял - все там же при определении типа которое производится при вызове callable.
    Написано
  • Почему function wrapper с ссылкой в сигнатуре может принимать pointer to member function?

    Dyikot
    @Dyikot Автор вопроса
    Евгений Шатунов, 1) В качетсве примера function wrapper я и использую std::function, а не свою реализацию чтобы все поняли. Определение std::function взято из cppreference
    Class template std::function is a general-purpose polymorphic function wrapper.

    2)
    Делегат, т.е. std::function, не умеет захватывать указатели на методы.

    Как это не может если все может?
    struct MyStruct
    {
    	void Test(int){}
    };
    std::function<void(MyStruct&, int)> f = &MyStruct::Test;
    Написано
  • Почему function wrapper с ссылкой в сигнатуре может принимать pointer to member function?

    Dyikot
    @Dyikot Автор вопроса
    Евгений Шатунов, На примере стандартного function wrapper:
    template<typename TSender, typename TEventArgs.
    using EventHandler = std::function<void(TSender&, TEventArgs)>;

    Всегда думал что методы просто функции которые первым аргументом принимают указатель на объект класса, и тут получается он может принимать и ссылку на объект класса. И вот вопрос был как можно оба? Или ссылка неявно к указаетлю преобразовывается. Все равно в памяти один вариант должен быть.
    Написано
  • Почему function wrapper с ссылкой в сигнатуре может принимать pointer to member function?

    Dyikot
    @Dyikot Автор вопроса
    Евгений Шатунов, Вопрос был про то что почему метод принимает и ссылку(*this), а не только указатель(this).
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    rPman, Буду иметь в виду. Буду решать проблемы по мере их поступления.
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    Ничего не понял что вы хотели сказать.
    1) Мне windows only решения не нужны.
    2) В SDL есть способ включить VSync. Но я делаю не игру и рендеринг у меня не каждый кадр а при изменениии соостояния объектов. И поэтому я не могу использовать VSync.
    3) И интервалы я не жду а проверяю прошло ли время. И причем тут асинхронная задержка и зажержка кадра тоже не понял.
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    res2001, Если задержка нужна постоянная то тогда да, но если нет то окно в 10мс есть.
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    res2001, У меня отдельный класс Timer использует std::condition_variable_any и обеспечивает хорошую точность, по крайней мере по сравнению с std::this_thread::sleep_for.
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    res2001, Делаю на Windows. Планирую выпустить на всех desktop плафтормах. Для сихронных задержек < 10мс я использую SDL_DelayNS.
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    Mercury13, 1 секунду я примерно написал, для того времени не критично, но например если 100мс, то да. Опять же задежка у меня привязана к частоте монитора. И тут уже погрешности не постоянна. И чтобы невелировать этот рандом тогда лучше будет проверять на другом потоке и возобновлять сопрограмму на нем же.
    Сделал проверку как в c# реализовано и там разные тоже потоки. Думаю сделать аналогичным образом.
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    Mercury13, чтобы не блокировать поток?
    Написано
  • Как лучше реализовать асинхронную задержку?

    Dyikot
    @Dyikot Автор вопроса
    Mercury13, Это да. Сейчас по сути я это и делаю все в одном потоке. Я думаю перенести логику проверки прошло ли время в другой поток для точности. На основном (UI) потоке у меня опрос производится с задержкой допустим каждые 16мс. И например если я выполню следующее:
    co_await AsyncTasks::Delay(1000); // Ожидаю 1000 мс получаю 1008 мс

    И вот если перенести на другой поток то будет ок если продолжение будет выполнять на другом потоке или мне надо все равно ждать основной поток и на нем вызывать. Или может есть иной путь?
    Написано
  • А нужно ли заменять dynamic_cast?

    Dyikot
    @Dyikot Автор вопроса
    Решил я сделать проще. Просто не хотел чтобы IData знал об DataTemplate.
    void ContentUIElement::SetContent(Ref<IData> content)
    {
    	SetProperty(ContentProperty, _content, content);
    
    	auto dataTemplate = content->GetDefaultDataTemplate();
    	if(dataTemplate != nullptr)
    	{
    		SetContentTemplate(std::move(dataTemplate));
    	}
    	else
    	{
    		InvalidateMeasure();
    		InvalidateContentPresenter();
    	}
    }
    Написано
  • А нужно ли заменять dynamic_cast?

    Dyikot
    @Dyikot Автор вопроса
    Ваш подход имеет смысл. Я его реализовал. Но мне пришлось сделать один приватный метод публичным (InvalidateContentPresenter), не значительно но всеравно. И проблема то еще заключается в том что не только же для ContentUIElement нужен шаблон данных. Например если реализовать следующие элементы с шаблонами данных ItemsControl, DataGrid, Expander, TabControl и т.д. И что мне тогда делать для каждого свой метод в IData? Или сделать интерфейс для них всех? Что если где-то будет не будет вообще автоматического выбора шаблона как тут? Тогда уже будет не один вызов виртуального метода и как мне кажется чрезмерная сложность. И пока прежний подход выглядит не как худший вариант.
    Написано
  • А нужно ли заменять dynamic_cast?

    Dyikot
    @Dyikot Автор вопроса
    Евгений Шатунов, Ну я как раз написал чтобы не использывать шаблоны, я использую dynamic_cast. И ничего я не перепутал. Возможно я запутал применя слово "шаблон" и имея в виду шаблон данных(DataTemplate) и шаблон языка(template<>) Вот пример:
    void ContentUIElement::SetContent(Ref<IData> content)
    	{
    		SetProperty(ContentProperty, _content, content);
    
    		if(content.Is<UIElement>()) // dynamic_cast
    		{
    			SetContentTemplate(UIElementDataTemplate());
    		}
    		else if(content.Is<TextContent>())  // dynamic_cast
    		{
    			SetContentTemplate(TextDataTemplate());
    		}
    		else
    		{
    			InvalidateMeasure();
    			InvalidateContentPresenter();
    		}
    	}
    Написано
  • Какой подход выбрать для представления Chunk?

    Dyikot
    @Dyikot Автор вопроса
    Wataru, Не понял как реализовать view, без своих итераторов? Я так только сделал для OrderedView. Но для ChunkView не совсем понимаю.
    Написано
  • Какой подход выбрать для представления Chunk?

    Dyikot
    @Dyikot Автор вопроса
    Wataru, Второй раз будет итерация в for. Первая происходит в operator++.
    Написано
  • Какой подход выбрать для представления Chunk?

    Dyikot
    @Dyikot Автор вопроса
    Wataru, Реализация
    итератора
    class ChunkIterator
    {
    private:
    	TRange& _range;
    	size_t _size;
    	TIterator _begin;
    	TIterator _end;
    public:
    	constexpr ChunkIterator(TRange& range, size_t size, TIterator begin):
    		_range(range),
    		_size(size),
    		_begin(begin),
    		_end(begin)
    	{
    		MoveNext();
    	}
    
    	constexpr auto operator*() const
    	{
    		return std::ranges::subrange(_begin, _end);
    	}
    
    	constexpr ChunkIterator& operator++()
    	{
    		MoveNext();
    		return *this;
    	}
    
    	constexpr ChunkIterator operator++(int)
    	{
    		ChunkIterator tmp = *this;
    		++(*this);
    		return tmp;
    	}
    
    	constexpr bool operator==(const ChunkIterator& other) const
    	{
    		return _begin == other._begin && _end == other._end;
    	}
    
    	constexpr bool operator!=(const ChunkIterator& other) const
    	{
    		return !(*this == other);
    	}
    
    	void MoveNext()
    	{
    		_begin = _end;
    		std::ranges::advance(_end, _size, _range.end());
    	}
    };

    Написано