Skip to content

Вызов функтора в std::string::resize_and_overwrite, пока не хватит места. #631

@orefkov

Description

@orefkov

В C++23 в std::string добавили очень удобный метод resize_and_overwrite.

Однако не всегда при его вызове нам известен нужный размер, и узнать мы его сможем только уже внутри функтора.
Например, так работают многие функции WinAPI - если им передать недостаточный буфер, они вернут нужный размер.

Предлагаю в методе resize_and_overwrite, если функтор вернул размер больше, чем текущая ёмкость строки, резервировать нужный размер и вызывать функтор повторно.

Пример, в Windows:

std::wstring p;
p.resize_and_overwrite(MAX_PATH, [](wchar_t* ptr, size_t capacity) -> size_t {
    DWORD len = GetCurrentDirectoryW(capacity + 1, ptr);
    if (len <= capacity) {
        return len;
    }
    return len - 1;
});

Обычно длина пути в Windows не превышает MAX_PATH, и такого буфера достаточно. Но бывают возможны и более длинные пути.

Пример в Linux

std::string p;
p.resize_and_overwrite(DEFAULT_PATH_LEN, [](char* p, size_t s) {
    const char* res = getcwd(p, s + 1);
    if (res) {
        return strlen(res); // Возвращаем длину строки
    }
    if (errno == ERANGE)  // Не влезло в буфер, попробуем в два раза больше
        return s * 2;
    return 0ul;
});

И вообще, такую бы штуку хорошо было добавить в конструктор.
Реализация подобного есть в simstr.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions