Question

I noticed one unpleasant thing that happens with std::pair when tried to save it into binary file: std::pair is aligned to a word. It might be useful in terms of processor efficiency, but requires more storage space, so I want to switch align 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 doesn't work:

#pragma pack(1)
    typedef std::pair< double, size_t > Q;

    std::cout << sizeof( Q ) << '\n';                               // 16
Was it helpful?

Solution 2

Sorry, the pack pragma won't work for you in this situation. You could

#define _CRT_PACKING 1
#include <utility>

This can cause ALL SORTS of problems. One of which 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 deal with the situation where it's not; which could lead to unceremonious crashing.

If you really want the object to be serialised like this, handle the serialisation of std::pair<U,V> yourself (example only):

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 want to handle the special case for data types that don't memcpy well.

What you really should do, for any serious project, is serialise objects in a portable way so that they're retrievable and elegantly handle things like floating point, different encodings for signed data types, pointers, arrays, STL containers and anything else where a simple dump of the object's memory is not possible or is insufficient.

Read the C++ FAQ and develop your own serialisation modules which are more than just dumping the in-memory representation of the object to file.

Alternatively, you can use a pre-packaged portable solution for serialising data types such as

OTHER TIPS

A std::pair basically reduces down to:

class xxx
{
   T1 _t1;
   T2 _t2;
};

The alignment of the two members is defined by the alignment in force when the template itself is defined, not just when it's used to instantiate an instance.

The Microsoft implementation of the STL uses the symbol _CRT_PACKING to define the packing used for all STL components. By default the packing is set to 8. If you define this symbol yourself before including the header that defines std::pair (<utility>) you can theoretically override the packing and set your own.

Be aware of potential problems you may encounter calling libraries or other code that assumes the standard packing.

Alright, totally different 'solution' that may or may not be a good idea, but hey if it works who am I to stop you from knowing. It comes with all of the same caveats as the other answers, but allows you to pick and choose your poisons.

Do a partial specialization of std::pair for the types that you care about, using the pragma pack for that particular definition, ex. for char and int:

namespace std {
#pragma pack( /* ... whatever you want ... */ )
template<> struct pair<char,int> {
  char first;
  int second;
};
}

With the definition somewhere you can touch it, you can affect the packing. Again, this is only good if you're willing to do it for all relevant types, and keep in mind the caveats mentioned by the other posters.

and there's the small chance that the library you're using is crazy and decided to put more stuff in pair that the rest of the lib depends on, but you probably don't need to worry about it

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top