Learn » Examples » Program Example User Traits

The full code for this magistrate example can be found here: examples/checkpoint_example_user_traits.cc

Example source code:

#include <checkpoint/checkpoint.h>

struct checkpoint_trait {} CheckpointTrait;
struct shallow_trait {} ShallowTrait;

using checkpoint::has_user_traits_v;
using checkpoint::has_any_user_traits_v;

namespace test {
  struct random_trait {} RandomTrait;

  struct TestObj {
    int a = 1;

    TestObj() {}

    template<
      typename SerT,
      typename std::enable_if_t<
        not has_user_traits_v<SerT, shallow_trait>, void*
      > = nullptr
    >
    void serialize(SerT& s){
      if constexpr(has_user_traits_v<SerT, checkpoint_trait>){
        if(s.isSizing()) printf("Customizing serialization for checkpoint\n");
        s | a;
      } else {
        if(s.isSizing()) printf("Default serializing testObj\n");
      }

      static_assert(not has_user_traits_v<SerT, shallow_trait>,
          "ShallowTrait should have been removed!\n");
    }
  };
}

namespace test {
  template<
    typename SerT,
    typename std::enable_if_t<
      has_user_traits_v<SerT, random_trait>, void*
    > = nullptr
  >
  void serialize(SerT& s, TestObj& myObj){
    if(s.isSizing()){
      printf("Inserting random extra object serialization step! ");
    }
    myObj.serialize(s);
  }

  template<
    typename SerT,
    typename std::enable_if_t<
      has_user_traits_v<SerT, shallow_trait>, void*
    > = nullptr
  >
  void serialize(SerT& s, TestObj& myObj){
    if(s.isSizing()) printf("Removing shallow trait before passing along!\n");
    auto newS = s.template withoutTraits<shallow_trait>();
    myObj.serialize(newS);
  }
}

namespace misc {
  template<
    typename SerT,
    typename std::enable_if_t<
      has_user_traits_v<SerT, test::random_trait>, void*
    > = nullptr
  >
  void serialize(SerT& s, test::TestObj& myObj){
    if(s.isSizing()){
      printf("Serializers in other namespaces don't usually get found ");
    }
    myObj.serialize(s);
  }


  const struct namespace_trait {} NamespaceTrait;
  template<
    typename SerT,
    typename std::enable_if_t<
      has_user_traits_v<SerT, namespace_trait>, void*
    > = nullptr
  >
  void serialize(SerT& s, test::TestObj& myObj){
    if(s.isSizing()){
      printf("A misc:: trait means we can serialize from misc:: too: ");
    }
    myObj.serialize(s);
  }


  const struct hook_all_trait {} HookAllTrait;
  template<
    typename SerT,
    typename T,
    typename std::enable_if_t<
      has_user_traits_v<SerT, hook_all_trait>, void*
    > = nullptr
  >
  void serialize(SerT& s, T& myObj){
    if(s.isSizing()){
      printf("We can even add on a generic pre-serialize hook: ");
    }
    auto newS = s.template withoutTraits<hook_all_trait>();
    myObj.serialize(newS);
  }
}
#include "checkpoint/checkpoint.h"

#include "checkpoint_example_user_traits.h"

int main(int, char**){
  using namespace test;
  TestObj obj;

  //Each invocation will be handled based on the traits attached
  auto s_info_a = checkpoint::serialize(obj);
  auto s_info_b = checkpoint::serialize<TestObj, checkpoint_trait>(obj);
  auto s_info_c = checkpoint::serialize<TestObj, checkpoint_trait, checkpoint_trait>(obj);
  auto s_info_d = checkpoint::serialize<TestObj, random_trait, checkpoint_trait>(obj);
  auto s_info_e = checkpoint::serialize<TestObj, checkpoint_trait, random_trait>(obj);
  auto s_info_f = checkpoint::serialize<TestObj, random_trait, random_trait>(obj);
  auto s_info_g = checkpoint::serialize<TestObj, shallow_trait>(obj);
  auto s_info_h = checkpoint::serialize<TestObj, misc::namespace_trait>(obj);
  auto s_info_i = checkpoint::serialize<TestObj, misc::hook_all_trait>(obj);
}