简体   繁体   中英

Operator overload for compound dereference and assignment

With C++ operator overloads, it is possible to create a class which emulates a pointer type, so I was experimenting with abstracting FILE read operations with this approach.

class FilePointer
{
    FILE* file;
    size_t position;
    FilePointer (FILE* file, size_t position)
    {
        this->file = file;
        this->position = position;
    };
    public:
    FilePointer (FILE* file)
    {
        this->file = file;
        this->position = 0;
    };
    FilePointer operator+ (size_t offset)
    {
        return FilePointer(file,position + offset);
    };
    FilePointer operator++ () // Prefix : ++FilePointer
    {
        position++;
        return *this;
    };
    FilePointer operator++ (int) // Postfix : FilePointer++
    {
        FilePointer before = *this;
        position++;
        return before;
    };
    FilePointer operator+= (size_t offset)
    {
        position += offset;
        return *this;
    };
    uint8_t operator* ()
    {
        fseek(file,position,SEEK_SET);
        Uint8 out;
        fread(&out,1,1,file);
        return out;
    };
    uint8_t operator[] (size_t offset)
    {
        return *(*this + offset);
    };

};

As can be seen in the above code snippet I was able to find out how to differentiate between the variations of increment operator so that given FilePointer f; f++ and ++f would behave intuitively.

What if I want to use this class for file writes , though? Currently I can grab a byte uint8_t something = f[0]; and it works, but if I want to "set" something, ie f[0] = 100; , the overloads as they are will not work for this.

Aside from whether or not this is "good practice" (though feel free to weigh in about that too), is there a way to implement this behavior in operator overloads for a class?

uint8_t n = f[0];
n++;
f[0] = n;

Or, getting even fancier, something like this:

f[1]++;

One way I imagine it could be done is by implementing yet another class which represents a "dereferenced FilePointer", but was curious if it is possible to do with only the overloads in the FilePointer class itself.

One way I imagine it could be done is by implementing yet another class which represents a "dereferenced FilePointer"

That's pretty much the only way to do it. It'd be an object of a "proxy type" that can be converted to uint8_t (possibly implicitly in a case like this, although in general I loath implicit conversions) but can also be assigned to.

It would have to be constructed with a FilePointer* , and be a friend so that it can invoke the appropriate "write" functionality.

It's going to be a bit minging, though, because it could become "dangling" very quickly, writing in the wrong place. You could also store the current position at the time the proxy object is constructed, and seek back to that position iff necessary at the time of writing. But all that seeking is not very performant.

Also reading one byte at a time is sloooooow.

Overall though your attempt is admirable, I would advise against the approach overall. You can at least wrap FILE* in a nice class that does fclose for you if it goes out of scope.

but was curious if it is possible to do with only the overloads in the FilePointer class itself.

I don't think so. Whatever you return from operator[] needs some magic state that can accept a value to "set" and connect to the FILE* machinery. Returning a uint8_t is simply never going to allow you to do that.

Another approach to improve the performance of 1 character writes might be that your proxy file pointer is actually a buffer that collects a number of assignments somehow, and then spools them all to the file on destruction.

One thing to be aware of with the proxy approach is the caller could keep hold of a number of your proxy objects using auto or auto& , and attempt to update them out of order. I don't think there is an efficient way to resolve this issue.

Also, what about operator -- ? Though the c++ library does have the concept of one-way iterators. perhaps iterators are the better metaphor?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM