I can't say I have a problem with the VirtualFile class itself and if is just copy/paste code from another library then I can't really fault you for the bit manipulation nightmare inside.
I do have a piece of advice though concerning the function template
Code: Select all
template<class PTR> MemoryBlock<PTR> getPointer( uint32_t nElements )
{
uint32_t byteSize = nElements * sizeof( *PTR );
/* ... */
}
What happens if PTR is not a pointer? C++ has static_assert for compile time assertions and here's a good place for it.
Code: Select all
template<class PTR> MemoryBlock<PTR> getPointer( uint32_t nElements )
{
static_assert( std::is_pointer_v<PTR>, "VirtualFile::getPointer() template parameter must be a pointer type." );
uint32_t byteSize = nElements * sizeof( *PTR );
/* ... */
}
In regards to the typedefs I have two things to say.
1) the typedefs that I posted have been in the
C standard for a while, they aren't specific to C++, but you can prefix them with std:: if you wanted, but isn't necessary. Microsoft typedefs are almost exclusively CAPITALIZED like UINT, DWORD and the like.
2) Please for the love of God, don't use typedef. I pray for the annihilation of that syntax some day. C++11 gave us the 'using' keyword to create aliases. It is more flexible since you can use it with templates and the interface is much cleaner and clearer. C reads right to left
DEFINING A TYPE ALIAS
typedef unsigned int DWORD;
C++11 onward is trying to move to left to right reading
using DWORD = unsigned int;
DEFINING A FUNCTION POINTER TYPE
void Func() {}
typedef void( *fn )( );
fn mfunc = &Func;
using Fn = void( *)( );
Fn mFunc = &Func;
Aside from that, to me typedef is misleading as you aren't defining a type, you are defining an alias. Using isn't much better in that regard, but it is logical to say "I'm using DWORD instead of unsigned int".
I believe when it was first introduced in C, it WAS a way of defining a new type because C's structs and enums are declarations unless you prepend them with typedef.
Code: Select all
typedef struct MyStruct_{ /*members*/ }MyStruct;
or
Code: Select all
struct MyStruct_{ /*members*/ };
typedef Mystruct_ MyStruct;
Because this:
Code: Select all
struct MyStruct{ /*members*/ }MyStruct;
If I recall correctly creates a variable named MyStruct of type MyStruct_ without the typedef decoration. It's been awhile since I programmed in C, so I may have that wrong. I know that's the behavior in C++ ( creating a variable instead of defining an alias).
As you can see, I'm pretty adamant about switching people over to using 'using' instead of typedef for aliasing. It's a small thing to some and old habits type hard I suppose ( ahem, chili, ahem WHA? ).
As to the template comment, what do you mean by "early vs late binding"? That wasn't in the list of pros LOL.