nop
nop

Reputation: 6353

Failed to randomize bytes using independent_bits_engine

I'm trying to randomize a byte array, but it doesn't let me compile it, because of the errors below. It doesn't even work with byte instead of std::uint8_t.

error C2338: invalid template argument for independent_bits_engine: N4659 29.6.1.1 [rand.req.genl]/1f requires one of unsigned short, unsigned int, unsigned long, or unsigned long long

message : see reference to class template instantiation 'std::independent_bits_engine<std::mt19937,8,unsigned char>' being compiled

error C2338: note: char, signed char, unsigned char, char8_t, int8_t, and uint8_t are not allowed

template<std::size_t N>
void generate_random_key(std::uint8_t(&iv_buff)[N])
{
    using random_bytes_engine = std::independent_bits_engine<std::default_random_engine, CHAR_BIT, std::uint8_t>;
    random_bytes_engine rbe;

    std::generate(std::begin(iv_buff), std::end(iv_buff), std::ref(rbe));
}

Upvotes: 1

Views: 839

Answers (1)

Ted Lyngmo
Ted Lyngmo

Reputation: 117698

[rand.req.genl]/1.6 (in the C++23 draft):

Throughout this subclause [rand], the effect of instantiating a template:

that has a template type parameter named UIntType is undefined unless the corresponding template argument is cv-unqualified and is one of unsigned short, unsigned int, unsigned long, or unsigned long long.

So, the effect is according to the standard undefined since you're not using one of the mentioned types.

You can use an unsigned short to get the same effect:

template<std::size_t N>
void generate_random_key(std::uint8_t(&iv_buff)[N])
{
    using random_bytes_engine = std::independent_bits_engine<std::default_random_engine,
                                                             CHAR_BIT, unsigned short>;
    random_bytes_engine rbe;

    std::generate(std::begin(iv_buff), std::end(iv_buff), rbe);
}

If you get a warning (like "conversion from unsigned short to _Ty, possible loss of data"), you could wrap the call to rbe in a lambda and do a static_cast:

    std::generate(std::begin(iv_buff), std::end(iv_buff), [&rbe]() {
        return static_cast<std::uint8_t>(rbe());
    });

Upvotes: 2

Related Questions