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
类,则一切正常,例如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;
}
};
并成功调用:
Storage<int, StringHandleWrapper> s;
std::string handle = s.AddValue(new int(N));
但我无法弄清楚如何将第二个模板参数STORAGE
添加到StringHandleWrapper
,以便它可以包装DumbPtrVec
或SmartPtrVec
中的任何一个。 ..
如果我将StringHandleWrapper
更改为:
template <typename T, template<typename> typename STORAGE>
class StringHandleWrapper : STORAGE<T>
{
using super = typename STORAGE<T>;
//... rest unchanged
然后我无法弄清楚如何实例化Storage
类,因为编译器抱怨“模板参数太少”:
Storage<int, StringHandleWrapper<SmartPtrVec>> s;
我希望我错过了一些简单的事情......
感谢您花时间浏览我的长篇问题!
答案 0 :(得分:1)
为部分参数应用创建另一个级别的模板:
template <template <typename, template<typename> typename> class W,
template <typename> typename S>
struct Apply
{
template <typename T> using type = W<T, S>;
};
然后像这样实例化Storage
:
Storage<int, Apply<StringHandleWrapper, SmartPtrVec>::type> s;
答案 1 :(得分:0)
刚刚找到答案(确实很简单):
我需要介绍两个单参数模板
module.exports
并在module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
]
}
实例化中使用新名称,例如
template<typename T> using StringDumbHandleWrapper = StringHandleWrapper<T, DumbPtrVec>;
template<typename T> using StringSmartHandleWrapper = StringHandleWrapper<T, SmartPtrVec>;
长期以来的问题...... :)