Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Making this function more like C++ and less like C

I have this function which opens /dev/urand and reads into a pointer of size; however it’s very C like and not very C++ like. I want to make the function look more like modern C++.

void URand::getrandom(uint64_t* r,uint8_t s){
    FILE* f = fopen("/dev/urandom","rb");
    assert(f);
    
    switch (s) {
        case 8:
            fread(r,sizeof(uint8_t),1,f);
            break;
        case 16:
            fread(r,sizeof(uint16_t),1,f);
            break;
        case 32:
            fread(r,sizeof(uint32_t),1,f);
            break;
        case 64:
            fread(r,sizeof(uint64_t),1,f);
            break;
        default:
            break;
    }
    
    fclose(f);
}

So the first issue is I’m passing uint64_t if I might not even need a variable of that size , if I only need 1 byte then I should pass in uint8, or 2 bytes then uint16.
The other is I’m passing in the number of bits needed to be read. Can this be automated?
Can I for example pass in the type(uint8_t) as an argument itself so the function knows which type its dealing with and the size its dealing with? I can’t do sizeof(r) because r is a pointer.

Maybe function overloading could be a solution where I have a different type for each argument?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

void URand::getrandom(uint8_t* r);
void URand::getrandom(uint16_t* r);
void URand::getrandom(uint32_t* r);
void URand::getrandom(uin64_t* r);

I get that’s a more pleasant solution than what I have; however I think with modern C++ it could be done even nicer and cleaner.

>Solution :

I would probably do something like this:

template<typename Unsigned>
Unsigned dev_urandom()
{
    Unsigned u;
    std::ifstream("/dev/urandom", std::ios::binary).read((char*)&u, sizeof(u));
    return u;
}

int main()
{
    std::cout << dev_urandom<unsigned int>() << '\n';
}

Or, if you prefer:

template<typename Unsigned>
void dev_urandom(Unsigned& u)
{
    std::ifstream("/dev/urandom", std::ios::binary).read((char*)&u, sizeof(u));
}

int main()
{
    unsigned u;
    dev_urandom(u);
    std::cout << u << '\n';
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading