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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions