질문 :C++ 래퍼 템플릿 : 템플릿 매개 변수로 전달하는 방법은 무엇입니까?
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
template <typename T>
class DumbPtrVec
{
std::vector<T*> m_vec;
public:
using handle = size_t;
~DumbPtrVec() {
std::for_each(begin(m_vec), end(m_vec), [](T* p){ delete p; });
}
handle AddElement(T* p) {
const handle index = m_vec.size();
m_vec.push_back(p);
return index;
}
T* GetElement(const handle& i) {
T* p = (i < m_vec.size())? m_vec[i] : nullptr;
return p;
}
};
template <typename T>
class SmartPtrVec
{
std::vector<std::shared_ptr<T>> m_vec;
public:
using handle = std::weak_ptr<T>;
handle AddElement(T* p) {
m_vec.emplace_back(p);
return m_vec.back(); // gets converted to weak_ptr
}
T* GetElement(const handle& i) {
T* p = (i.expired())? nullptr : i.lock().get();
return p;
}
};
template <typename T, template<typename> typename STORAGE>
class Storage
{
STORAGE<T> m_values;
public:
using handle = typename STORAGE<int>::handle;
handle AddValue(T* v) { return m_values.AddElement(v); }
T* GetValue(handle h) { return m_values.GetElement(h); }
};
int main()
{
constexpr int N = 13;
Storage<int, DumbPtrVec> d;
auto dh = d.AddValue(new int(N));
std::cout << *d.GetValue(dh) << " == " << N <<std::endl;
Storage<int, SmartPtrVec> s;
auto sh = s.AddValue(new int(N));
std::cout << *s.GetValue(sh) << " == " << N << std::endl;
return 0;
}
: 나는 두 개의 템플릿 "정책"을 만들었습니다
바보 또는 스마트 포인터 중 하나의 벡터에 어떤 값 유형의 스토리지를 구현, (이 올바른 용어입니다 있는지 확실하지 않습니다)
모든 것이 제대로 작동합니다.
그런 다음 템플릿 "래퍼"를 추가했습니다.이 래퍼는 "handle"요소를 고유 한 문자열로 바꾸고 문자열을 핸들로 다시 변환하기위한 참조 테이블을 유지합니다. 이 클래스가 DumbPtrVec
또는 SmartPtrVec
클래스에서 명시 적으로 파생되면 모든 것이 작동합니다 (예 :
template <typename T>
class StringHandleWrapper : SmartPtrVec<T>
{
using super = typename SmartPtrVec<T>;
using Str2HandleMap = std::unordered_map<std::string, typename super::handle>;
Str2HandleMap m_Name2HandleMap;
public:
using handle = std::string;
handle AddElement(T* p) {
typename super::handle elem = super::AddElement(p);
static int counter = 0;
std::string uuid = std::to_string(++counter);
m_Name2HandleMap[uuid] = elem;
return uuid;
}
T* GetElement(const handle& uuid) {
auto it = m_Name2HandleMap.find(uuid);
return (it != m_Name2HandleMap.end())? super::GetElement(it->second) : nullptr;
}
};
성공적인 호출 : SmartPtrVec
에 대한
Storage<int, StringHandleWrapper> s;
std::string handle = s.AddValue(new int(N));
그러나 나는 그것이 DumbPtrVec
또는 중 하나를 포장 할 수 있도록, StringHandleWrapper
에, 두 번째 템플릿 매개 변수, STORAGE
를 추가하는 방법을 알아낼 수 없습니다
template <typename T, template<typename> typename STORAGE>
class StringHandleWrapper : STORAGE<T>
{
using super = typename STORAGE<T>;
//... rest unchanged
: 나는
StringHandleWrapper
에 변경하는 경우
SmartPtrVec
...
컴파일러는 "너무 적은 템플릿 인수"에 대해 불평로
그때, Storage
클래스를 인스턴스화하는 방법을 알아낼 수 없습니다 :
Storage<int, StringHandleWrapper<SmartPtrVec>> s;
을 나는 간단하게 뭔가를 누락 희망 ...
감사합니다 내 긴 질문을 보면서 시간을내어 주셔서 감사합니다!
제안 해 주셔서 감사합니다. 알아 둘만한. – Boris