UPD: Вопрос решён. Помогла функция glutTimerFunc(), убираем glutPostRedisplay() из idle-функции, создаём таймер с обновлением в 1000/FPS_LIMIT миллисекунд и создаём новый таймер в том таймере, тем самым таймер создаёт другой таймер и так по кругу.
std::vector<std::string>
, а std::set<std::string>
и все те же две std::unordered_map<std::string_view, std::string_view>
. Set позаботится о том, чтобы хранить только уникальные строки. У std::set
, кстати, тоже есть функция emplace
. std::map
, а std::unordered_nap
. Тебе стоит самостоятельно понять принципиальную разницу этих контейнеров и почему первый в твоей задаче непригоден.std::unordered_map<std::string, std::string>
. Первый контейнер хранит прямой перевод, второй - обратный перевод. Контейнеров два т.к. слова в разных языках могут писаться одинаково, а значения у них могут быть разные и переводы, следовательно, тоже разные.emplace
. Изучи документацию и найди для себя обоснование - почему именно эта функция будет эффективнее всего работать с парой std::string_view
в качестве параметров.std::string
в качестве параметров шаблона std::unordered_nap
таково, что TranslateForward
возвращает std::string_view
, который не владеет памятью на которую ссылается. Вместе с этим, тип std::string_view
не рассматривается как тип долгосрочного хранения (рассматривать его как долгосрочное хранилище - в большинстве случаев опасно). Такая сигнатура требует от Translator
владеть памятью строк возвращаемых из функций Translate*
. В самой задаче использование string_view оправдано экономией памяти.
Translator::Add(string("first"), string("second"))
- первое выделение делается вот тут. Зачем?data.emplace_back(first)
- второе выделение делается вот тут и ниже во втором emplace_back
.std::string_view
в качестве типа параметров твоей функции?srand((unsigned)time(NULL));
- в течении секунды твое зерно будет одинаковым, а следовательно и все нарисованные точки тоже будут одинаковыми. Функция time
возвращает текущее количество секунд в UTC формате. Тебе не стоило писать эту строчку в displayFunction
, тебе стоило написать ее в main
точно перед glutInit
.glutPostRedisplay
внутри idle-функции - это правильно, так в GLUT и поступает запрос на перерисовку кадра. Что мне надо сделать? - Отрыть файл.
Какой файл открыть? - Значит или путь файла известен внутри функции, или передается параметром.
Для чего открыть файл: для записи или для чтения? - Видимо или функция должна своими именем об этом говорить, или режим работы с файлом надо передавать параметром.
А что делать с дескриптором открытого в функции файла? - Возвращать, пожалуй.
А что если файл не удалось открыть? - Наверное надо предусмотреть обработку ошибок и возвращать недействительный дескриптор файла.
Зачем мне нужен дескриптор открытого файла? - Чтобы считать оттуда что-либо или записать туда что-либо.
Что мне надо сделать чтобы считать из файла что-либо? - ...
Что мне надо сделать чтобы записать в файл что-либо? - ...
Что мне делать с дескриптором открытого файла когда он больше не нужен? - ...
Но вот вынести в отдельные функции Создание файла, Запись данных и Считывание данных не могу.