1 분 소요

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

그런데 템플릿을 통해 건네주는 람다함수는
위와 같이 건네준다

그리고 빌드하니…

Image

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 타입에 좀 더 주의를 기울일 것!

rvalue 관련 블로깅

댓글남기기