代码之家  ›  专栏  ›  技术社区  ›  Tyler Jackson

有时从可变模板函数中调用函数

  •  -1
  • Tyler Jackson  · 技术社区  · 8 年前

    我有一个基本的消息类,用于序列化数据,然后通过套接字发送该数据:

    std::vector<char> m_rawMessageData;
    int m_currentReadPosition = 0;
    
    template<typename writeDataType>
    void LoadData(writeDataType &inData)
    {
        int dataSize = sizeof(writeDataType);
        int currentSize = m_rawMessageData.size();
    
        m_rawMessageData.resize(dataSize + m_rawMessageData.size());
        std::memcpy(&m_rawMessageData.at(currentSize), &(inData), dataSize);
    }
    
    template<typename ReadDataType>
    int GetData(ReadDataType &outData)
    {
        std::stringstream dataReader;
    
        int dataSize = sizeof(ReadDataType);
    
        if (m_currentReadPosition + dataSize > m_rawMessageData.size())
            return 0;
    
        std::memcpy(&outData, &m_rawMessageData.at(m_currentReadPosition),
            dataSize);  
    
        m_currentReadPosition += dataSize;
    
        return dataSize;
    }   
    

    我知道如果这些代码调用不正确,可能会出现一些错误,但我是目前唯一的开发人员,我需要一些工作。此外,我假设只传递基本类型,并且两端的结束性是相同的。

    我希望这个消息类能够处理结构。我的想法是:在我的每个结构中,我将编写一个“序列化/反序列化”函数。然后,在我的LoadData和GetData调用中,我将检查是否存在“序列化/反序列化”函数,然后调用它,而不是执行一般的memcpy。

    我能够使用类似于此问题中的代码检查是否存在序列化函数: Check if a class has a member function of a given signature

    但我不确定该如何调用“Serialize”函数。我不能简单地使用“inData.Serialize()”,因为它无法编译。

    简而言之,我希望我的LoadData函数看起来像这样:

    template<typename writeDataType>
    void LoadData(writeDataType &inData)
    {
        //Check if writeDataType has Serialize Function. 
        if (serializeDoesExist)
        {
             inData.Serialize(m_rawMessageData);
        }
        else
        {
            int dataSize = sizeof(writeDataType);
            int currentSize = m_rawMessageData.size();
    
            m_rawMessageData.resize(dataSize + m_rawMessageData.size());
            std::memcpy(&m_rawMessageData.at(currentSize), &(inData), dataSize);
        }
    }
    

    任何帮助都将不胜感激。

    注意:我的老板不喜欢在项目中添加外部库,除非绝对必要。这就是为什么我没有使用Protobuf或类似的东西。

    3 回复  |  直到 8 年前
        1
  •  1
  •   Jarod42    8 年前

    具有 std::experimental::isdetected ,您可以创建特征:

    template<class T>
    using serialize_t = decltype(std::declval<T>().Serialize());
    
    template <typename T>
    using has_serialize = std::experimental::is_detected<serialize_t, T>;
    

    然后,使用SFINAE:

    template<typename writeDataType>
    std::enable_if_t<has_serialize<writeDataType>::value>
    LoadData(writeDataType &inData)
    {
        inData.Serialize(m_rawMessageData);
    }
    
    template<typename writeDataType>
    std::enable_if_t<!has_serialize<writeDataType>::value>
    LoadData(writeDataType &inData)
    {
        int dataSize = sizeof(writeDataType);
        int currentSize = m_rawMessageData.size();
    
        m_rawMessageData.resize(dataSize + m_rawMessageData.size());
        std::memcpy(&m_rawMessageData.at(currentSize), &(inData), dataSize);
    }
    
        2
  •  0
  •   SoronelHaetir    8 年前

    我建议您编写一个LoadData/GetData对,使用std::enable\u if专门化,检查是否存在所需的成员。专用表单使用这些成员,而通用表单继续使用memcpy

        3
  •  0
  •   Lucky    8 年前

    可以使用try-catch语句检查此函数是否存在。

    try{
        inData.Serialize();
    }catch(<You can specify the exception here, or just write "..." to catch any exception>...){
        <What you want to do if the function does not exists>
    }
    

    如果您需要有关try-catch和异常处理的更详细信息: https://www.tutorialspoint.com/cplusplus/cpp_exceptions_handling.htm