Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 使用c+自动进行结构反序列化/转换+;模板_C++11_Templates_C++14 - Fatal编程技术网

C++11 使用c+自动进行结构反序列化/转换+;模板

C++11 使用c+自动进行结构反序列化/转换+;模板,c++11,templates,c++14,C++11,Templates,C++14,我有一些C数据接口(pod结构),每个接口都有不同的版本,每个版本都有反序列化功能。 (完整代码如下) 用户类型: typedef struct sInterface_v1_t { int i; }Interface_v1_t; typedef struct sInterface_v2_t { int i; int j; }Interface_v2_t; typedef struct sInterface_v3_t { int j; float u; }Interface

我有一些
C
数据接口(pod结构),每个接口都有不同的版本,每个版本都有反序列化功能。 (完整代码如下)

用户类型:

typedef struct sInterface_v1_t {
  int i;
}Interface_v1_t;

typedef struct sInterface_v2_t {
  int i;
  int j;
}Interface_v2_t;

typedef struct sInterface_v3_t {
  int j;
  float u;
}Interface_v3_t;

// latest version
typedef Interface_v3_t Interface_t;


void Interface_v1_deserialize(std::stringstream& io_str, Interface_v1_t* o_d)
{
  io_str >> o_d->i;
}
void Interface_v2_deserialize(std::stringstream& io_str, Interface_v2_t* o_d)
{
  io_str >> o_d->i;
  io_str >> o_d->j;
}
void Interface_v3_deserialize(std::stringstream& io_str, Interface_v3_t* o_d)
{
  io_str >> o_d->j;
  io_str >> o_d->u;
}
序列化的数据流对数据类型和版本号进行编码,因此易于分派

//                    type interfaceversion data...        
std::string data_1 = "I 1 5";
std::string data_2 = "I 2 7 2";
std::string data_3 = "I 3 1 3.54";
我想创建一个总是输出最新类型的泛型反序列化

最后,反序列化代码应该如下所示:

std::stringstream s(data_1); // or data_2 or data_3
s >> ts;  // remove type from string (type dispatching will be later one level above)
Interface_t i = { 0 };

Interface_Deserializer<Interface_t>::instance().deserialize(s, &i);
我创建了一组可以实现这一点的模板(见下面的完整列表),但是用户必须创建一些锅炉板代码才能让它们工作

用户锅炉板

template <>
struct InterfaceVersionHelper<Interface_t, 1> :InterfaceVersionHelperBase<Interface_t, Interface_v1_t, 1, &Interface_v1_deserialize>
{};


template <>
struct InterfaceVersionHelper<Interface_t, 2> :InterfaceVersionHelperBase<Interface_t, Interface_v2_t, 2, &Interface_v2_deserialize>
{};

template <>
struct InterfaceVersionHelper<Interface_t, 3> :InterfaceVersionHelperBase<Interface_t, Interface_v3_t, 3, &Interface_v3_deserialize>
{};

static bool r1 = []() {
  InterfaceVersionHelper<Interface_t, 1>::registerMe();
  InterfaceVersionHelper<Interface_t, 2>::registerMe();
  InterfaceVersionHelper<Interface_t, 3>::registerMe();
  return true;
}();

template <>
struct LatestInterface<Interface_t> :public Interface_LatestVersion<Interface_t, 3> {};
template <>
struct InterfaceVersionHelper<Interface_t, 1> :InterfaceVersionHelperBase<Interface_t, Interface_v1_t, 1, &Interface_v1_deserialize>
{};


template <>
struct InterfaceVersionHelper<Interface_t, 2> :InterfaceVersionHelperBase<Interface_t, Interface_v2_t, 2, &Interface_v2_deserialize>
{};

template <>
struct InterfaceVersionHelper<Interface_t, 3> :InterfaceVersionHelperBase<Interface_t, Interface_v3_t, 3, &Interface_v3_deserialize>
{};

static bool r1 = []() {
  InterfaceVersionHelper<Interface_t, 1>::registerMe();
  InterfaceVersionHelper<Interface_t, 2>::registerMe();
  InterfaceVersionHelper<Interface_t, 3>::registerMe();
  return true;
}();

template <>
struct LatestInterface<Interface_t> :public Interface_LatestVersion<Interface_t, 3> {};
static bool r =
InterfaceRegistererDefintion<
  Interface_t,
  InterfaceV<Interface_v3_t, 3, &Interface_v3_deserialize>,
  InterfaceV<Interface_v2_t, 2, &Interface_v2_deserialize>,
  InterfaceV<Interface_v1_t, 1, &Interface_v1_deserialize>
>::create();
#include <list>
#include <map>
#include <iostream>
#include <sstream>
#include <memory>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#include <functional>



template <typename T>
using DeserFun = void(std::stringstream&, T*);

template<typename IFACE>
void DummyDeser(std::stringstream& io_str, IFACE* o_d) {};

template <typename T>
struct InterfaceVersionHelperBaseBase {
  using value_type_target = T;
  virtual int  version()const = 0;
  virtual void deserialize(std::stringstream& io_str, T* o_d) = 0;
};

template <typename T, int LatestVersion>
struct Interface_LatestVersion {
  enum {
    version = LatestVersion
  };
  using value_type = T;

};


template <typename T>
struct LatestInterface :public Interface_LatestVersion<T, 0> {};

template <typename T>
struct Interface_Deserializer {

  using value_type = T;

  std::map<int, std::shared_ptr<InterfaceVersionHelperBaseBase<T>>> versionMap;

  static Interface_Deserializer& instance() {
    static Interface_Deserializer s_instance;
    return s_instance;
  };

  void deserialize(std::stringstream& io_str, T* o_d)const {
    int v = 0;
    io_str >> v;
    auto it = versionMap.find(v);
    if (it != versionMap.end()) {
      (*it).second->deserialize(io_str, o_d);
    } else {
      std::cerr << "unknown version " << v << " for " << typeid(T).name() << std::endl;
    }
  }

private: 
  Interface_Deserializer() {};
};



template <typename T, typename IFACE, int IFACE_VER, DeserFun<IFACE> DESER_FUN>
struct InterfaceVersionHelperBase : public InterfaceVersionHelperBaseBase<T>
{

  using value_type_current = IFACE;


  enum { ver = IFACE_VER };
  int  version()const override { return IFACE_VER; };

  /// deserializes stream and converts to latest type 
  void deserialize(std::stringstream& io_str, T* o_d) override {
    value_type_current o;
    DESER_FUN(io_str, &o);
    Converter<T, IFACE_VER, LatestInterface<T>::version>::convert(&o, o_d);
    return;
  };

  /// registers helper for this interface version on the Interface_Deserializer
  static void registerMe() {
    std::pair<int, std::shared_ptr<InterfaceVersionHelperBaseBase<T>>> v;
    v.first = IFACE_VER;
    v.second.reset(new InterfaceVersionHelperBase<T, IFACE, IFACE_VER, DESER_FUN>());
    Interface_Deserializer<T>::instance().versionMap.insert( v );
  }
};


/// this has to be specialized for each interface version to point to the correct types and deserializer
template <typename IFACE, int IFACE_VER>
struct InterfaceVersionHelper :public InterfaceVersionHelperBase < IFACE, IFACE, 0, &DummyDeser<IFACE> >
{

};


/// generic converter that converts between two interface versions by converting the input one version up
/// by calling user convert function
/// this can also be specialized by used to implement specific from x to latest converter
template <typename IFACE, int IFACE_VER, int IFACE_VER2>
struct Converter {

  static void convert(const typename InterfaceVersionHelper < IFACE, IFACE_VER>::value_type_current*  i_d,
                            typename InterfaceVersionHelper < IFACE, IFACE_VER2>::value_type_current* o_d)
  {
    InterfaceVersionHelper < IFACE, IFACE_VER + 1>::value_type_current temp;
    ::convert(i_d, &temp);
    Converter<IFACE, IFACE_VER + 1, IFACE_VER2>::convert(&temp, o_d);
  }

};


/// converter specialization that aborts conversion, if both sides are the same interface versions
template <typename IFACE, int IFACE_VER>
struct Converter<IFACE, IFACE_VER, IFACE_VER>{

  static void convert(const typename InterfaceVersionHelper < IFACE, IFACE_VER>::value_type_current*  i_d,
    typename InterfaceVersionHelper < IFACE, IFACE_VER>::value_type_current* o_d)
  {
    *o_d = *i_d;
  }
};




/////////////////////////////
// user types / deserializers
/////////////////////////////


typedef struct sInterface_v1_t {
  int i;
}Interface_v1_t;

typedef struct sInterface_v2_t {
  int i;
  int j;
}Interface_v2_t;

typedef struct sInterface_v3_t {
  int j;
  float u;
}Interface_v3_t;

// latest version
typedef Interface_v3_t Interface_t;


void Interface_v1_deserialize(std::stringstream& io_str, Interface_v1_t* o_d)
{
  io_str >> o_d->i;
}
void Interface_v2_deserialize(std::stringstream& io_str, Interface_v2_t* o_d)
{
  io_str >> o_d->i;
  io_str >> o_d->j;
}
void Interface_v3_deserialize(std::stringstream& io_str, Interface_v3_t* o_d)
{
  io_str >> o_d->j;
  io_str >> o_d->u;
}




/////////////////////////////
// user converter
/////////////////////////////


static void convert(const Interface_v1_t* i_d, Interface_v2_t* o_d) {

  o_d->i = i_d->i;
  o_d->j = 0;
}

static void convert(const Interface_v2_t* i_d, Interface_v3_t* o_d) {

  o_d->j = i_d->j;
  o_d->u = 0.f;
}



// specialization for specific conversion
template <>
struct Converter<Interface_t, 1, 3> {

  static void convert(const Interface_v1_t* i_d,
                            Interface_v3_t* o_d)
  {
    o_d->u = float(i_d->i);
    o_d->j = 0;
  }
};




/////////////////////////////
// user boiler plate
/////////////////////////////

template <>
struct InterfaceVersionHelper<Interface_t, 1> :InterfaceVersionHelperBase<Interface_t, Interface_v1_t, 1, &Interface_v1_deserialize>
{};


template <>
struct InterfaceVersionHelper<Interface_t, 2> :InterfaceVersionHelperBase<Interface_t, Interface_v2_t, 2, &Interface_v2_deserialize>
{};

template <>
struct InterfaceVersionHelper<Interface_t, 3> :InterfaceVersionHelperBase<Interface_t, Interface_v3_t, 3, &Interface_v3_deserialize>
{};

static bool r1 = []() {
  InterfaceVersionHelper<Interface_t, 1>::registerMe();
  InterfaceVersionHelper<Interface_t, 2>::registerMe();
  InterfaceVersionHelper<Interface_t, 3>::registerMe();
  return true;
}();

template <>
struct LatestInterface<Interface_t> :public Interface_LatestVersion<Interface_t, 3> {};



/*

// desired user boiler plate:

static bool r =
InterfaceRegistererDefintion<
  Interface_t,
  InterfaceV<Interface_v3_t, 3, &Interface_v3_deserialize>,
  InterfaceV<Interface_v2_t, 2, &Interface_v2_deserialize>,
  InterfaceV<Interface_v1_t, 1, &Interface_v1_deserialize>
>::create();

*/ 

/////////////////////////////
// user test data
/////////////////////////////

std::string data_1 = "I 1 5";
std::string data_2 = "I 2 7 2";
std::string data_3 = "I 3 1 3.54";

std::string data_4 = "I 4 1 3.54 3.14159";



int main(int argc, char* argv[])
{
  std::string ts; 
  int ti;

  { // test deserializer
    std::stringstream s1(data_1);
    std::stringstream s2(data_2);
    std::stringstream s3(data_3);

    s1 >> ts >> ti; // remove type and version  from string
    s2 >> ts >> ti; //
    s3 >> ts >> ti; //

    Interface_v1_t i1 = { 0 };
    Interface_v2_t i2 = { 0 };
    Interface_v3_t i3 = { 0 };


    Interface_v1_deserialize(s1, &i1);
    Interface_v2_deserialize(s2, &i2);
    Interface_v3_deserialize(s3, &i3);
  }

  {// test helper deserialziation and conversion
    std::stringstream s1(data_1);
    std::stringstream s2(data_2);
    std::stringstream s3(data_3);

    s1 >> ts >> ti; // remove type and version  from string
    s2 >> ts >> ti; //
    s3 >> ts >> ti; //

    Interface_t i1 = { 0 };
    Interface_t i2 = { 0 };
    Interface_t i3 = { 0 };

    InterfaceVersionHelper< Interface_t, 1> h1; 
    InterfaceVersionHelper< Interface_t, 2> h2;
    InterfaceVersionHelper< Interface_t, 3> h3;

    h1.deserialize(s1, &i1);
    h2.deserialize(s2, &i2);
    h3.deserialize(s3, &i3);



  }
  {// test Interface_Deserializer
    std::stringstream s1(data_1);
    std::stringstream s2(data_2);
    std::stringstream s3(data_3);
    std::stringstream s4(data_4);

    s1 >> ts;  // remove type from string
    s2 >> ts;  //
    s3 >> ts;  //
    s4 >> ts;  //

    Interface_t i1 = { 0 };
    Interface_t i2 = { 0 };
    Interface_t i3 = { 0 };
    Interface_t i4 = { 0 };

    auto ds = Interface_Deserializer<Interface_t>::instance();

    ds.deserialize(s1, &i1);
    ds.deserialize(s2, &i2);
    ds.deserialize(s3, &i3);
    ds.deserialize(s4, &i4); // should output an error

  }

  return 0;
}