質問:C++ラッパーテンプレート:テンプレートパラメータとして渡す方法は? 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;
}
:私はダムやスマートのいずれかのポインタのベクトルでいくつかの値型のストレージを実装する2つのテンプレート「政策」(これは正しい用語であるかどうかわからないが)、作成した
これまでのところすべてうまくいきます。
次に、要素「ハンドル」を一意の文字列で置き換え、文字列をハンドルに戻すルックアップテーブルを保持するテンプレートラッパーを追加しました。このクラスが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));
しかし、それはDumbPtrVec
のいずれか、またはを包むことができるように、私は、StringHandleWrapper
に、STORAGE
、2番目のテンプレートパラメータを追加する方法を見つけ出すことはできません
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;
私は、単純な何かが欠けてる願っています...
はありがとう私の長い質問を見てあなたの時間を取るために!私は、例えば、2つの単一のパラメータテンプレート
template<typename T> using StringDumbHandleWrapper = StringHandleWrapper<T, DumbPtrVec>;
template<typename T> using StringSmartHandleWrapper = StringHandleWrapper<T, SmartPtrVec>;
を導入し、Storage
インスタンス化で新しい名前を使用するために必要な
:
ありがとうございます!知っておいてよかった。 – Boris