2017-04-24 2 views
0

모듈 식 시리얼 라이저를 만들어야합니다. 나는 msgpack을 사용하고있다.템플릿 매개 변수 팩 serialization

그래서, 간단한 양식은 다음과 같이 내장되어 있습니다 :

enum class FieldId 
{ 
    Time, 
    Pressure 
}; 

struct TimeFieldConfig 
{ 
    typedef long long DataType; 
    const static FieldId id = FieldId::Time; 
} 

struct PressureFieldConfig 
{ 
    typedef double DataType; 
    const static FieldId id = FieldId::Pressure; 
} 

struct BaseField 
{ 
    virtual void dump(std::ofstream &buffer) const = 0; 
}; 

template<class T> 
struct Field : BaseField 
{ 
    void dump(std::ofstream &buffer) 
    { 
    msgpack::pack(buffer, values); 
    } 
    std::vector<typename T::DataType> values; 
} 

struct Recorder 
{ 
    template <class T> 
    void insertField() 
    { 
     data.insert_or_assign(T::id, new Field<T>); 
    } 

    template <class T> 
    void add(const typename T::DataType &v) 
    { 
     if (data.find(T::id) != data.cend()) 
      reinterpret_cast<Field<T> *>(data[T::id])->add(v); 
    } 

    void dump(const std::string fpath) 
    { 
     std::ofstream outFile; 
     outFile.open(fpath, std::ios::binary); 

     // headers 
     std::vector<int> keys; 
     for (const auto &k : data) 
      keys.push_back(static_cast<int>(k.first)); 
     msgpack::pack(outFile, keys); 

     // values 
     for (const auto &k : data) 
      k.second->dump(outFile); 

     outFile.close(); 
    } 

    std::map<FieldId, BaseField *> data; 
} 

int main(int arc, char* argv[]) 
{ 
    Recorder r; 
    r.insertField<TimeFieldConfig>(); 
    r.insertField<PressureFieldConfig>(); 

    /* add data ... */ 
    r.dump("data.dat"); 
} 

덤프가 잘 작동, 모든 데이터와 헤더가 존재한다. 이제 녹음 된 데이터를 다시로드하고 싶습니다.

제 질문은 동적으로 필요한 필드를 삽입하는 Recorder의 인스턴스를 어떻게 만듭니 까?

+0

너무 광범위합니다. 이미 시도한 바가 있습니까? 어디서 붙어 있었 니? –

답변

0

나는 그것이 도움이 될 수 있기를 바랍니다.

내가 만들고자하는 것은 레지스트리 패턴입니다. 이것이 내가 해낸 방식입니다.

// may be a singleton 
class FieldFactory 
{ 
public: 
    FieldFactory() 
    { 
    } 
    ~FieldFactory() 
    { 
    } 

    template <class T> 
    void registerField() 
    { 
     creators.insert_or_assign(T::id, &Field<T>::creator); 
    } 

    BaseField *create(FieldId fid) 
    { 
     return creators[fid](); 
    } 

private: 
    typedef std::function<BaseField *()> FieldCreator; 
    std::map<FieldId, FieldCreator> creators; 
}; 

다음 주에, 클래스

필드 템플릿 클래스 추가에
FieldFactory ff; 
ff.registerField<TimeFieldConfig>(); 
ff.registerField<PressureFieldConfig>(); 

등록을 호출

static BaseField *creator() 
{ 
    return new Field<T>(); 
} 

을 그리고 Recorder 클래스의로드 함수를 만들 :

void reload(const std::string &filePath) 
{ 
    std::ifstream inFile; 
    inFile.open(filePath, std::ios::binary); 

    std::vector<char> buffer((std::istreambuf_iterator<char>(inFile)), (std::istreambuf_iterator<char>())); 
    inFile.close(); 

    // headers 
    std::size_t off = 0; 
    std::vector<int> keys; 

    msgpack::object_handle result; 
    msgpack::unpack(result, buffer.data(), buffer.size(), off); 
    result.get().convert(keys); 

    // create fields 
    for (auto k : keys) 
    { 
     FieldId fid = static_cast<FieldId>(k); 
     data.insert_or_assign(fid, m_ff->create(fid)); 
    } 

    // values 
    for (auto k : keys) 
    { 
     msgpack::object_handle oh; 
     msgpack::unpack(oh, buffer.data(), buffer.size(), off); 

     FieldId fid = static_cast<FieldId>(k); 
     if (data.find(fid) != data.cend()) 
      data[fid]->reload(oh); 
    } 
} 

어쩌면 impr 나는 추측한다. 그러나 그것은 생각이다.

관련 문제