기존 코드를 다시 작성하는 중입니다. 이전에는 모든 대답 정보가 메모리의 문자열 배열에 저장되었습니다. 데이터 유형에 따라 데이터가 여러 위치에서 변형되었습니다. 아래는 내가 목표로 삼고있는 설정의 빠른 모의 다. 본질적으로 몇 가지 질문이 있습니다. 데이터베이스에 저장된 답변의 구조는 데이터 유형에 따라 다릅니다. 일반적으로 void *를 사용하지 말고 적절한 유형으로 캐스팅합니다. 그러나 lambda를 사용하여 일반 코드를 실행하거나 데이터 유형을 알 수있는 경우 특정 코드를 실행할 수있는 더 나은 솔루션을 찾을 수 없습니다. 모든 응답을 미리 정의 된 규칙에 따라 모든 대답에 적용하기 때문에 모든 답변을 동일한 벡터에 저장해야하므로 템플릿 클래스는 도움이되지 않습니다.타입 안전 코드와 런타임 의사 결정의 결합
모든 조언을 주시면 감사하겠습니다.
#include <vector>
#include <memory>
struct AddressData
{
wchar_t Line1[50];
wchar_t Line2[50];
long CountrySeqNo;
AddressData()
{
memset(this, 0, sizeof(*this));
};
};
struct GenericData
{
wchar_t value[200];
GenericData()
{
memset(this, 0, sizeof(*this));
};
};
enum class DataType
: short
{
GENERIC,
ADDRESS
};
class AnswerBase
{
protected:
const void* const data;
const DataType dataType;
protected:
AnswerBase(const DataType datatype, const void* const _data)
: dataType(datatype), data(data)
{
if (data == nullptr)
throw std::exception("Data may not be initialized as NULL");
};
public:
/*
Some generic methods here that would apply logic by means of lambdas etc - these would be overwritten in the derived classes
*/
template<typename T> const T& GetData() { static_assert(false, "The given type is not supported"); };
template<>
const GenericData& GetData()
{
if (DataType::GENERIC != dataType)
throw std::exception("The requested type does not match the value that initialised data");
return *static_cast<const GenericData* const>(data);
};
template<>
const AddressData& GetData()
{
if (DataType::ADDRESS != dataType)
throw std::exception("The requested type does not match the value that initialised data");
return *static_cast<const AddressData* const>(data);
};
};
class AddressAnswer
: public AnswerBase
{
public:
AddressAnswer()
: AnswerBase(DataType::ADDRESS, &answer)
{
};
protected:
AddressData answer;
};
class GenericAnswer
: public AnswerBase
{
public:
GenericAnswer()
: AnswerBase(DataType::GENERIC, &answer)
{
};
protected:
GenericData answer;
};
int main()
{
std::vector<std::shared_ptr<AnswerBase>> answers;
answers.push_back(std::make_shared<GenericAnswer>());
answers.push_back(std::make_shared<AddressAnswer>());
// In some parts of code - interact with generic methods without needing to check the underlying data type
// ....
// ....
// In parts of code where we know we are dealing with a given type - like saving to a DB
auto val1 = answers[0]->GetData<GenericData>().value;
auto val2 = answers[1]->GetData<AddressData>().Line1;
// this will give a runtime failure
//auto val3 = answers[0]->GetData<AddressData>().Line1;
return 0;
}
'void *'대신'varaint'를 사용할 수 있습니다. – Jarod42
변형에 대해 생각해 보았습니다.하지만 VC++에서 C++ 17을 아직 지원하지 않아서 - 큰 프로젝트가 아닌 내 프로젝트에 부스트 라이브러리를 포함해야합니다. 변형 멤버가 기본 클래스에 계속 존재합니까? – Floris