Время компиляции сужает wchar к char - PullRequest
0 голосов
/ 25 октября 2019

В моей функции времени компиляции я бы хотел работать со строками. ОБА ANSI и ШИРОКИЙ. Итак, я добавил быстрый шаблон для обработки обоих. Это все просто, но у меня есть специальная функция, которая вычисляет контрольную сумму безопасности для строк. Это работает с байтовым массивом, и потребовалось бы довольно много усилий, чтобы переписать его для работы с переменным размером буфера, поэтому я подумал, что просто сузлю wchar до char и разрешу моей функции работать с ним. По умолчанию он не работает так, как я думал.

Пример кода для воспроизведения моей проблемы: https://godbolt.org/z/ya2zq7

#include <iostream>

constexpr void hack(const char* const from, const size_t fromLen, char* const to)
{
    for (size_t i = 0; i < fromLen; i++)
    {
        to[i] = from[i] + 1;
    }
}

template <typename U, std::size_t LENGTH>
class EncryptedStorage
{
    U m_data[LENGTH]{};

public:
    constexpr EncryptedStorage(const U* input)
    {
        hack(static_cast<const char* const>(input), LENGTH * sizeof(U), static_cast<char* const>(m_data));
    }
};

int main()
{
    // Test with CHAR
    constexpr char test[] = "Hello World";
    constexpr size_t size = sizeof(test) / sizeof(test[0]);
    constexpr auto encrypted = EncryptedStorage<char, size>(test);

    // test with WCHAR
    constexpr wchar_t wtest[] = L"Hello World";
    constexpr size_t wsize = sizeof(wtest) / sizeof(wtest[0]);
    constexpr auto wencrypted = EncryptedStorage<wchar_t, wsize>(wtest);
}

Если вы прокомментируете широкие строки, он будет отлично скомпилирован. Можно ли делать то, что я хочу, или мне действительно нужно переделать весь мой алгоритм для работы с переменным размером?

1 Ответ

0 голосов
/ 25 октября 2019

Основная проблема в вашем коде состоит в том, что вы не можете использовать static_cast для преобразования между указателями на разные типы данных - когда эти типы не связаны , как char и wchar_t;для этого вам потребуется приведение в стиле reinterpret_cast или C:

constexpr EncryptedStorage(const U* input)
{
    hack(reinterpret_cast<const char* const>(input), LENGTH * sizeof(U), reinterpret_cast<char* const>(m_data));
}

Однако, если у вас есть такое приведение, ваша функция EncyptedStorage больше не может быть оценена во время компиляции,поэтому два объявления constexpr в вашем main потерпят неудачу, и вам придется просто использовать const вместо этого:

const auto encrypted = EncryptedStorage<char, size>(test);
const auto wencrypted = EncryptedStorage<wchar_t, wsize>(wtest); // Can't use constexpr

РЕДАКТИРОВАТЬ: Другой способ (возможно, более приятный) - использовать function-style casts:

using pcchar = const char* const;
using pchar = char* const;
constexpr EncryptedStorage(const U* input)
{
    hack(pcchar(input), LENGTH * sizeof(U), pchar(m_data));
}

При этом вы можете использовать constexpr для encrypted, но не для wencrypted!

...