2017-11-29 9 views
-1

가변 인자 템플릿 내에서 함수를 호출 이 코드에서이 코드가 잘못 호출되었지만 지금 당장 유일한 개발자 일 뿐이며 작동하도록해야합니다. 또한, 기본 유형 만 전달되며 양 끝단의 동일성은 가정합니다.은 가끔 데이터를 직렬화 한 후 소켓을 통해 데이터를 전송하기 위해 사용하고 난 기본 메시지 클래스가 기능

이 메시지 클래스가 구조체를 처리 할 수있게하려고합니다. 내 생각은 이것이었다 : 각각의 구조체에서 "Serialize/Deserialize"함수를 작성할 것이다. 그런 다음 내 LoadData 및 GetData 호출에서 "Serialize/Deserialize"함수가 있는지 확인한 다음 일반 memcpy를 호출하는 대신 호출합니다. Check if a class has a member function of a given signature

하지만 내가 "직렬화"함수를 호출하는 가정하고 방법을 잘 모르겠어요 :

나는이이 질문의 코드와 유사한 것을 사용하여 직렬화 기능을 있는지 확인 할 수 있었다. 나는 단순히 "inData.Serialize()"를 사용할 수 없다. 컴파일에 실패하기 때문이다.

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

어떤 도움이 많이 주시면 감사하겠습니다 :

그래서 짧은에, 나는 나의 LoadData 기능이 같은 것을보고 싶다.

참고 : 내 상사는 꼭 필요한 경우를 제외하고는 프로젝트에 외부 라이브러리를 추가하지 않습니다. 그것이 내가 Protobuf 또는 비슷한 것으로 가지 않은 이유입니다.

답변

1

를 계속 사용하면서 전문화 된 형태의 해당 구성원을 사용, 당신은 특성을 만들 수 있습니다 다음

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); 
} 
+0

아주 좋기 때문에 감지 단계가 단순 해집니다. C++ 14에서만이 작업을 수행 할 수 있습니까? 그렇지 않다면 나는 우아하고 직선적이기 때문에이 글을 답으로 표시 할 것입니다. –

+0

'std :: experimental :: detected'는 C++ 11로 구현 될 수 있습니다. (link는 가능한 구현을 제공하고,'std :: void_t '는 C++ 11에서도 가능하다.) – Jarod42

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

당신이 시도 - 캐치와 예외 처리에 대한 자세한 정보를 원하는 경우 https://www.tutorialspoint.com/cplusplus/cpp_exceptions_handling.htm

+0

난 몰라 "inData"가 typename이기 때문에 이것이 작동한다고 믿습니다. 문제는 내가 inData.Serialize() 처음 컴파일러 오류가 발생하므로 쓸 수 없습니다. –

+0

죄송합니다. 저의 실수는 "inData"를 인스턴스로 보았습니다. 그러면 SFINAE를 사용해야 할 것입니다. 이 질문을 확인하십시오 : https://stackoverflow.com/questions/257288/is-it-possible-to-write-a-template-to-check-for-a-functions-existence – Lucky

0
난 당신이 검사, 표준 : enable_if를 사용하여 전문됩니다 LoadData/GetData의 쌍을 작성하는 것이 제안

필요한 회원의 존재. 일반적인 형태의 std::experimental::isdetected으로 방어 적이기에게

+0

특별한 LoadData를 작성 하시겠습니까? 내 프로그램에서 정의한 모든 구조체의/GetData? 내가 생각하는 가능한 해결책이지만, 나는 그것을 일반적으로 유지하고 싶다. –

+0

아니요, std :: enable_if와 멤버 검색을 사용하여 멤버가있을 경우 멤버를 사용하지만 존재하지 않는 쌍이있는 전문화를 선택하면 memcpy가 계속 사용됩니다. 현재 및 현재 존재하지 않는 LoadData 및 GetData 형식 모두에 std :: enable_if 매개 변수 (조건이 참인 경우 다른 위치가 참인 경우)가 필요하다는 것을 알 수 있습니다.그렇게하면 각 LoadData/GetData에는 해당 코드 경로에 적합한 코드 만 있습니다. – SoronelHaetir