Return Type Operator
엔진 구조를 짜다보면 Collider나 Shader 같은 경우 Base Class를 통해 자식 Class를 만드는 경우가 많은데
해당 Resource를 관리할땐 BaseClass List로 관리를 하는 경우가 대부분이다.
이런 자식 Class가 생길때마다 Get하는 함수를 각각 만들어줄 때마다 깔끔하게 하나의 함수로 내보내고 싶다는 생각을 계속하게
되었는데 처음엔 std::valiant와 std::vist을 이용하려 했으나 직관적이지 못해 사용하지 않았다.
그러다 발견한 방법이 Type Operator인데 생각보다 복잡하지 않고 예외처리도 해당 Type들에 대한 정보만 있다면 쉽게 처리할 수 있었다.
Operator 방식
- 반환 하고 싶은 Type의 Operator를 보유한 Class를 하나 선언하여 각각 Type의 Operator를 추가하는 방식이다.
- 해당 Type Return Class 생성 방식을 반환하려는 Class의 Get하는 함수를 모두 보유한 Class를 멤버변수로 들고 있는다.
- 모든 Type의 반환 함수를 보유한 Class를 Type Operator Class와 friend class로 설정, 해당 Type Operator에서
해당하는 Get하는 함수를 반환 하는 형식.
class ShaderManager : public IShaderManager
{
public:
ShaderManager(ID3D11Graphic* graphic);
~ShaderManager();
public:
friend class OriginalShader;
public:
void Initialize() override;
void Release() override;
public:
ShaderBase* LoadShader(SHADER_TYPE shaderType, const char* fileName, const char* entry_point, const char* shaderName, const D3D_SHADER_MACRO* pDefines = nullptr);
OriginalShader GetShader(std::string shaderName) override;
private:
VertexShader* GetVertexShader(std::string shaderName);
PixelShader* GetPixelShader(std::string shaderName);
ComputeShader* GetComputeShader(std::string shaderName);
private:
// Shader List
std::unordered_map<std::string, ShaderBase*> m_ShaderList;
};
VertexShader* ShaderManager::GetVertexShader(std::string shaderName)
{
std::unordered_map<std::string, ShaderBase*>::iterator shader = m_ShaderList.find(shaderName);
// 해당 Shader가 없을 경우..
if (shader == m_ShaderList.end()) return nullptr;
switch (shader->second->GetType())
{
case SHADER_TYPE::VERTEX_SHADER:
return reinterpret_cast<VertexShader*>(shader->second);
default:
return nullptr;
}
}
PixelShader* ShaderManager::GetPixelShader(std::string shaderName)
{
std::unordered_map<std::string, ShaderBase*>::iterator shader = m_ShaderList.find(shaderName);
// 해당 Shader가 없을 경우..
if (shader == m_ShaderList.end()) return nullptr;
switch (shader->second->GetType())
{
case SHADER_TYPE::PIXEL_SHADER:
return reinterpret_cast<PixelShader*>(shader->second);
default:
return nullptr;
}
}
ComputeShader* ShaderManager::GetComputeShader(std::string shaderName)
{
std::unordered_map<std::string, ShaderBase*>::iterator shader = m_ShaderList.find(shaderName);
// 해당 Shader가 없을 경우..
if (shader == m_ShaderList.end()) return nullptr;
switch (shader->second->GetType())
{
case SHADER_TYPE::COMPUTE_SHADER:
return reinterpret_cast<ComputeShader*>(shader->second);
default:
return nullptr;
}
}
해당 Type들의 Get하는 함수를 모두 보유하고 있는 Class.
List에 있는 Base를 검색 후 해당 Type에 맞는 형태일 경우 해당 Type으로 Down Casting하여 반환.
/// <summary>
/// 여러가지 타입을 한개의 함수로 반환하기 위해 만든 Class
/// 해당 Class의 Type을 반영하여 원본 Class Operator를 통해 여러가지 타입으로 반환
/// </summary>
class ShaderManager;
class VertexShader;
class PixelShader;
class ComputeShader;
class OriginalShader
{
public:
ShaderManager* pThis;
std::string shaderName;
public:
operator VertexShader*();
operator PixelShader*();
operator ComputeShader*();
};
OriginalShader::operator VertexShader* ()
{
return pThis->GetVertexShader(shaderName);
}
OriginalShader::operator PixelShader* ()
{
return pThis->GetPixelShader(shaderName);
}
OriginalShader::operator ComputeShader* ()
{
return pThis->GetComputeShader(shaderName);
}
해당 Type들을 변환하여 반환해주는 Operator Class 선언.
위의 방식으로 하였을 경우 받으려는 Type이 찾은 Type과 다를경우 nullptr을 반환하게 되므로 다른 Type이 들어올 일은 없다.
'C++' 카테고리의 다른 글
[C++] Delegate & Function Pointer (0) | 2022.06.07 |
---|---|
[C++] Define Macro (0) | 2021.12.19 |
[C++] std::enable_if / std::is_base_of (0) | 2021.12.19 |