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

时间:2017-11-29 19:02:51

标签: c++ serialization

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

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;
}   

我知道如果这些代码被错误地调用,这段代码中可能存在一些错误/错误,但我现在是唯一的开发人员,我需要一些工作。另外,我假设只传递基本类型,并且两端的持久性是相同的。

我希望这个消息类能够处理结构。我的想法是这样的:在我的每一个结构中,我都会写一个&#34;序列化/反序列化&#34;功能。然后,在我的LoadData和GetData调用中,我将检查是否存在&#34;序列化/反序列化&#34;函数然后调用它而不是执行通用memcpy。

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

但我不确定我是怎么称呼#34; Serialize&#34;功能。我不能简单地使用&#34; inData.Serialize()&#34;,因为它无法编译。

简而言之,我希望我的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 个答案:

答案 0 :(得分:1)

使用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);
}

答案 1 :(得分:0)

您可以使用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

答案 2 :(得分:0)

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