3
저는 C++ 이동 기능을 간신히 사용했기 때문에 내가하고있는 일이 정확하다고 확신하지 못합니다. 내 코드를 살펴보고 내가 작성한 실수를 지적 해 주시면 감사하겠습니다.이 방법은 이동 참조와 unique_ptr을 사용하는 올바른 방법입니까?
아이디어는 키에 의해 저장된 리소스 맵을 만드는 것입니다. 자원은 복사 할 수없고 움직일 수 없습니다.
또한 클래스에는 생성자 및 소멸자 정의가 필요합니까?
감사합니다.
이std::map<int, std::unique_ptr<Foo>> m;
void add_to_map(int key, std::unique_ptr<Foo> val)
{
m[key] = std::move(val);
}
사용 : 기본적으로
add_to_map(1, std::unique_ptr<Foo>(new Foo(1, 2, 3)));
std::unique_ptr<Foo> p(new Foo(true, 'x'));
p->mutate();
add_to_map(std::move(p));
, 고유의 포인터를 전달
#define TYPE(x) std::identity<decltype(x)>::type
namespace General
{
template<class T>
std::string ToString(const T& x)
{
std::ostringstream ss;
ss << x;
return ss.str();
}
}
namespace General
{
template<class T, class KEY = std::string>
class ResourceManager
{
public:
typedef T ResourceType;
typedef KEY KeyType;
void Load(const KeyType& key, std::unique_ptr<ResourceType>&& resource);
const ResourceType& Read(const KeyType& key) const;
ResourceType& Modify(const KeyType& key);
void Unload(const KeyType& key);
std::unique_ptr<ResourceType>&& Release(const KeyType& key);
void UnloadAll();
private:
std::map<KeyType, std::unique_ptr<ResourceType>> data;
};
}
template<class T, class KEY>
void General::ResourceManager<T, KEY>::Load(const KeyType& key, std::unique_ptr<ResourceType>&& resource)
{
auto find_it = data.lower_bound(key);
if (find_it != data.end() && ! (data.key_comp()(key, find_it->first)))
{
throw std::runtime_error(General::ToString(key) + " already exists!");
}
else
{
data.insert(find_it, TYPE(data)::value_type(key, std::move(resource)));
}
}
template<class T, class KEY>
const typename General::ResourceManager<T, KEY>::ResourceType& General::ResourceManager<T, KEY>::Read(const KeyType& key) const
{
auto find_it = data.find(key);
if (find_it == data.end())
{
throw std::runtime_error(General::ToString(key) + " could not be found!");
}
else
{
return *find_it->second;
}
}
template<class T, class KEY>
typename General::ResourceManager<T, KEY>::ResourceType& General::ResourceManager<T, KEY>::Modify(const KeyType& key)
{
auto find_it = data.find(key);
if (find_it == data.end())
{
throw std::runtime_error(General::ToString(key) + " could not be found!");
}
else
{
return *find_it->second;
}
}
template<class T, class KEY>
void General::ResourceManager<T, KEY>::Unload(const KeyType& key)
{
auto find_it = data.find(key);
if (find_it == data.end())
{
throw std::runtime_error(General::ToString(key) + " could not be found!");
}
else
{
data.erase(find_it);
}
}
template<class T, class KEY>
std::unique_ptr<typename General::ResourceManager<T, KEY>::ResourceType>&& General::ResourceManager<T, KEY>::Release(const KeyType& key)
{
auto find_it = data.find(key);
if (find_it == data.end())
{
throw std::runtime_error(General::ToString(key) + " could not be found!");
}
else
{
auto resource = std::move(find_it->second);
data.erase(find_it);
return std::move(resource);
}
}
template<class T, class KEY>
void General::ResourceManager<T, KEY>::UnloadAll()
{
data.clear();
}
함수를 호출 한 사용자가 명시 적으로 객체를 내 value 매개 변수로 이동해야합니까? –
@NeilKirk : 발신자가 lvalue를 가지고 있으면 yes입니다. 그렇지 않으면 암시 적이며 추가 코드가 필요하지 않습니다 (첫 번째 사용 예 에서처럼). 그리고이 예제는'add_to_map (std :: make_unique (1,2,3)); '이어야합니다. 실제로 C++ 14가 필요합니다. –
Release 함수의 반환 유형은 어떻습니까? –