C2664 트러블 슈팅
EffectFactory 관련 빌드 에러(C2664)
Map<string, Factory> 패턴을 구현하던 중
한가지 문제가 발생하였다
using EffectFactory = std::function<std::unique_ptr<IEffect>()>;
class EffectManager
{
public:
static EffectManager& GetInstance();
void Register(std::string&& id, EffectFactory& ef);
std::unique_ptr<IEffect> Create(const std::string& id) const;
private:
EffectManager();
std::unordered_map<std::string, EffectFactory> effectMap;
};
매니저는 다음과 같이 EffectFactory 타입을 받아서
Map에 등록을 한다
#pragma once
#include"EffectManager.h"
namespace EffectTemplate
{
template<class T>
void RegisterEffectType()
{
static_assert(std::is_base_of_v<IEffect, T>, "RegisterEffectType에 이상한 타입 집어넣지 마세요!");
EffectManager& eManager = EffectManager::GetInstance();
// 내부에서 move로 가져가기에
T temp;
// 람다 내부에서 -> std::unique_ptr<IEffect> 로 반환 타입 명시
eManager.Register(temp.GetId(), []() {return std::make_unique<T>();});
}
template<class T>
struct EffectAutoRegister
{
EffectAutoRegister()
{
RegisterEffectType<T>();
}
};
#define REGISTER_EFFECT_TYPE(T) static EffectTemplate::EffectAutoRegister<T> _auto_register_##T;
};
그런데 템플릿을 통해 건네주는 람다함수는
위와 같이 건네준다
그리고 빌드하니…
C2664 에러가 발생하였다!
잘 읽어보니 ‘타입 변환’에 실패한 경우에 나타나는 ‘컴파일 에러’이다
- ‘람다 함수’는 rvalue의 임시객체이고
현재의 Register 함수는 lvalue ref인 &로 받고 있으니
타입 변환 오류가 생긴게 아닐까?
class EffectManager
{
public:
static EffectManager& GetInstance();
void Register(std::string&& id, EffectFactory&& ef);
std::unique_ptr<IEffect> Create(const std::string& id) const;
private:
EffectManager();
std::unordered_map<std::string, EffectFactory> effectMap;
};
위와 같이 EffectFactory 부분을
rvalue ref 인 &&로 수정하고 빌드하니
성공적으로 빌드되었다!
template<class T>
void RegisterEffectType()
{
static_assert(std::is_base_of_v<IEffect, T>, "RegisterEffectType에 이상한 타입 집어넣지 마세요!");
EffectManager& eManager = EffectManager::GetInstance();
// 내부에서 move로 가져가기에
T temp;
// 람다 내부에서 -> std::unique_ptr<IEffect> 로 반환 타입 명시
eManager.Register(temp.GetId(), []() -> std::unique_ptr<IEffect> {return std::make_unique<T>();});
}
- 또한 추가적으로 -> std::unique_ptr
코드를 추가하여
해당 람다함수가 반환하는 타입을 '명시적'으로 수정하였다
결론
‘람다식’ 과 같은 ‘임시 객체’를 사용할때는
Rvalue와 LValue 타입에 좀 더 주의를 기울일 것!
댓글남기기