C ++ class wrapper around basic types

Many libraries I've seen / used have typedefs to provide fixed-size portable variables like int8, uint8, int16, uint16, etc. that will be the right size regardless of the platform (and C ++ 11 does this with header stdint.h)

After recently using binary file I / O in a small library that I am writing, I see the advantage of using typedef in such a way as to ensure code portability.

However, if I am going to not print "namespace :: uint32" and not use the built-in fundamental types, I can also make the replacement as useful as possible. Therefore, I consider using classes instead of simple typedefs.

These wrapper classes will implement all the normal operators, so they can be used interchangeably with the main type.

For example:

int x = 0; //do stuff 

can be

 class intWrapper { //whatever }; intWrapper = 0; //do stuff 

without having to change any code in "// do stuff"

The reason I'm considering this approach, and not just typedefs, is because I already have functions that work with fundamental types, like

 std::string numberToString(double toConvert); std::string numberToHexString(double toConvert); int intToXSignificantPlaces(const int& number, unsigned char numberOfSignificantPlaces); bool numbersAreApproximatelyEqual(float tollerance); //etc.... 

Syntactically, it would be better (and more oop) to do the following:

 intWrapper.toString(); intWrapper.toHexString(); //etc 

It would also allow me to implement the bigint classes (int128, etc.) and have both the smaller ones (based on fundamental types) use the same interfaces.

Finally, each shell can have a static instance of max and min itself, so good syntax is possible int32 :: max and int32 :: min.

However, I have a few problems that I would like to address before doing this (since it is mostly syntactic sugar, and these types will be used as a rule, any additional overhead can have a significant impact on performance).

1) Is there an additional function that calls overhead when using someClass.operator + (), someClass.operator- (), etc. only through int a + int b? If so, will the + () operator attachment eliminate ALL of this overhead?

2) All external functions require a primitive type, for example, glVertex3f (float, float, float) cannot simply be passed 3 floatWrapper objects, is there a way to automatically force the compiler to make a floatWrapper for the float? If so, are there any performance implications?

3) Is there any additional memory overhead? I understand (?) That classes with inheritance have some kind of virtual table pointer and therefore use a little more memory (or is it just for virtual functions?), But assuming that these wrapper classes are not inherited from / are not child classes t any additional memory usage using classes instead of fundamental types?

4) Are there any other problems / performance implications that may arise?

+7
c ++ types portability typedef wrapper
source share
3 answers

1) Is there an additional function that causes overhead when using someClass.operator + ()

No, if the function body is small and in the header, it will be nested and there will be no overhead

2) Is there a way to automatically force the compiler to make a floatWrapper for the float?

 struct floatWrapper { floatWrapper(float); //implicit conversion from float operator float(); //implicit conversion to float. }; 

Again, if the function body is small in the header, it will be nested and there will be no overhead

3) Is there any additional memory overhead?

not if there are no virtual functions. A class is called polymorphic if it declares or inherits any virtual functions. If the class is not polymorphic, objects do not have to contain a pointer to a table of virtual functions. Moreover, the execution of dynamic_cast of a pointer / reference to a non-polymorphic class according to the hierarchy of inheritance to a pointer / reference to a derived class is unacceptable, therefore it is not necessary that the objects have some type information.

4) Are there any other problems / performance implications that may arise?

performance? Not.

Also, be sure to implement binary operators that do not modify lhs as free functions, and overload them to support all the corresponding permutations of floatWrapper and float .

 struct floatWrapper { explicit floatWrapper(float); operator float(); //implicit conversion to float. floatWrapper operator-=(float); }; floatWrapper operator-(floatWrapper lhs, floatWrapper rhs) {return lhs-=rhs;} floatWrapper operator-(float lhs, floatWrapper rhs) {return floatWrapper(lhs)-=rhs;} floatWrapper operator-(floatWrapper lhs, float rhs) {return lhs-=rhs;} 

Here is my attempt of this kind . Note that you will need a slightly different version for double-double / double / long.

+10
source share

It depends on the compiler. If it has loops or distributions, they are less likely to be nested.

+2
source share

I think the answers are not entirely correct - at least for gcc 4 I observed significant overhead due to constructor and operator calls.

The following takes about twice as much as with long :

 typedef intWrapperImpl<long> TestWrapper; //typedef long TestWrapper; int main (int argc, char** argv) { TestWrapper sum(0); TestWrapper test(4); for (long i = 0; i < 1000000000L; ++i) { sum += test; } cout << sum << "\n"; return 0; } 

Using different versions of gcc 4 with and without optimization did not lead to performance differences.

In this case, adding

 intWrapperImpl& operator+=(const intWrapperImpl & v) {value+=v.value; return *this;} 

gives only a slight improvement.

Using a wrapper as if it were the base type in performance-critical code seems like a bad idea. Using them locally and, thus, calling the constructor all the time seems even worse.

It really came as a surprise to me, because it would be easy to integrate everything in it and optimize it, as if it were a variable of a basic type.

Any further tips would be greatly appreciated!

0
source share

All Articles