2

Problem: I have a set of classes for which I have already implemented boost serialization methods. Now, I want to add an operator== to one class that contains many of the other classes as its members. This comparison should be straightforward: A deep, member wise comparison.

Idea: Since the existing serialization methods already tell the compiler everything it needs to know, I wonder if this can be used to generate efficient comparison operators.

Approach 1: The simplest thing would be to compare strings containing serializations of the objects to be compared. The runtime of this approach is probably much slower than handcrafted operator== implementations.

Approach 2: Implement a specialized boost serialization archive for comparisons. However, implementing this is much more complicated and time consuming than implementing either handcrafted operators or approach 1.

SebastianK
  • 3,582
  • 3
  • 30
  • 48

1 Answers1

0

I did a similar thing recently for hashing of serializable types:

Here I "abused" boost serialization to get a hash function for any Boost Multi Precision number type (that has a serializable backend).

The approach given in the linked answer is strictly more lightweight and much easier to implement than writing a custom archive type. Instead, I wrote a custom custom Boost Iostreams sink to digest the raw data. namespace io = boost::iostreams;

struct hash_sink {
    hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}

    typedef char         char_type;
    typedef io::sink_tag category;

    std::streamsize write(const char* s, std::streamsize n) {
        boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
        return n;
    }
  private:
    size_t* _ptr;
};

This is highly efficient because it doesn't store the archive anywhere in the process. (So it sidesteps the dreadful inefficiency of Approach 1)


Applying to Equality Comparison

Sadly, you can't easily equality compare in streaming mode (unless you can be sure that both streams can be consumed in tandem, which is a bit of finicky assumption).

Instead you would probably use something like boost::iostreams::device::array_sink or boost::iostreams::device::back_insert_device to receive the raw data.

If memory usage is a concern you might want to compress it in memory (Boost Iostreams comes with the required filters for zip/bzip too). But I guess this is not your worry - as you would likely not be trying to avoid duplicating code in that case. You could just implement the comparison directly.

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633