Std :: pair <U, V> alignment control
I noticed one unpleasant thing that happens to std :: pair when trying to save it in a binary file: std :: pair is word aligned. This may be useful in terms of processor efficiency, but it requires more storage space, so I want to switch the alignment mode to 1 byte for std :: pair. My compiler is MS VC ++ 2012.
#include <iostream> int main( ) { struct S_a { double a; size_t b; }; #pragma pack(1) struct S_wa { double a; size_t b; }; std::cout << sizeof( size_t ) << '\n'; // 4 std::cout << sizeof( double ) << '\n'; // 8 std::cout << sizeof( std::pair< size_t, size_t > ) << '\n'; // 8 std::cout << sizeof( std::pair< double, size_t > ) << '\n'; // 16 - bad std::cout << sizeof( S_wa ) << '\n'; // 12 - good std::cout << sizeof( S_a ) << '\n'; // 16 std::cout << sizeof( std::pair< double, double > ) << '\n'; // 16 } I tried this, but it does not work:
#pragma pack(1) typedef std::pair< double, size_t > Q; std::cout << sizeof( Q ) << '\n'; // 16 Sorry, the pragma pack will not work for you in this situation. You could
#define _CRT_PACKING 1 #include <utility> This can lead to problems with all problems. One of them is that certain APIs, especially low-level ones, expect data to be aligned in a certain way. Not all of them are smart enough to cope with a situation when this is not so; which can lead to an unceremonious failure.
If you really want the object to be serialized this way, handle the serialization of std::pair<U,V> yourself (just an example):
template<typename U, typename V> void paircpy(char *dest, const std::pair<U, V> &pair) { memcpy(buffer, &pair.first, sizeof(U)); memcpy(buffer + sizeof(U), &pair.second, sizeof(V)); } You would like to handle a special case for data types that do not have memcpy .
What you really need to do for any serious project is serialized objects in a portable way, so that they are retrieved and elegantly handle things like floating point, different encodings for signed data types, pointers, arrays, STL containers, and whatever otherwise, where a simple dump of the object's memory is impossible or insufficient.
Read the C ++ FAQ and create your own serialization modules that are more than just dumping the representation of an object into a file in memory.
Alternatively, you can use a pre-packaged portable solution to serialize data types such as
- Boost.Serialization
- Google Protocol Buffers
- XDR library
- JSON or XML
A std::pair basically boils down to:
class xxx { T1 _t1; T2 _t2; }; The alignment of two elements is determined by force alignment when the template itself is defined , and not just when creating an instance of the instance.
The Microsoft STL implementation uses the _CRT_PACKING symbol to determine the packaging used for all STL components. By default, the packaging is set to 8. If you yourself define this symbol before including the header that defines std::pair ( <utility> ), you can theoretically redefine the packaging and set your own.
Be aware of potential problems you may encounter when invoking libraries or other code that assumes standard packaging.
Well, a completely different βsolutionβ, which may or may not be a good idea, but if it works, who am I to stop you from knowing. It comes with all the same warnings as the other answers, but allows you to pick and choose poisons.
Partially specialize std::pair for types that interest you, using the pragma package for this particular definition, for example. for char and int :
namespace std { #pragma pack( /* ... whatever you want ... */ ) template<> struct pair<char,int> { char first; int second; }; } With a definition somewhere you can touch it, you can affect the packaging. Again, this is only good if you are ready to do this for all the relevant types and remember the warnings mentioned by other posters.
and there is a small chance that the library you are using is going crazy and decided to add more things to the pair , which the rest of the library depends on, but you probably don't need to worry about it