私はgroup_by
という名前の再帰的なマップクラスを作成しています。例えば連鎖したメソッド呼び出しを置き換えるvariadicメソッドを書く方法は?
は、GBの順に、std::string
、int
、そしてchar
キータイプによってグループ化foo
へのポインタを格納するgroup_by
オブジェクトです。
group_by<foo,std::string,int,char> gb;
group_by
現在のレベルのマップの内部を見るために使用することができるat(I const& key)
アクセサ方法を提供します。より深いマップを取得するためにat()
を呼び出すと、正常に動作します。
auto& v = gb.at(k1).at(k2).at(k3).get_vec();
私は、連鎖なしで、すべて1回の呼び出しで深くマップを取得することができますat_variadic(Args const& ...args)
と呼ばれるat()
の代替を作成したいと考えPROBLEM
。
auto& w = gb.at_variadic(k1, k2);
auto& x = gb.at_variadic(k1, k2, k3);
しかし、私はいくつかの問題を抱えています。まず第一に、返り値の型を指定する方法はわかりません。なぜなら、変数の引数に依存するからです。おそらくdecltype()
を使用しますか?
WORKING ANSWER
Ecatmur's answer below良いアプローチを概説しました。
私はコンパイラを幸せにするために、端末ケースgroup_by<>
で遊ばなければなりませんでしたが、Ecatmurの答えに大きく依存する以下のコードは、gcc 4.7.2でうまく動作しているようです。
#include <cassert>
#include <map>
#include <vector>
#include <iostream>
template< typename T, typename... Args >
struct group_by
{
using child_type = T;
std::vector<T*> m_vec;
void insert(T* t)
{
m_vec.push_back(t);
}
child_type&
at(size_t i)
{
return *m_vec[i];
}
};
template< typename T, typename I, typename... Args >
struct group_by<T,I,Args...>
{
using child_type = group_by<T,Args...>;
std::map<I,child_type> m_map;
void insert(T* t)
{
m_map[ *t ].insert(t);
}
child_type& at(I const& key)
{
return m_map.at(key);
}
template<typename... Ks>
auto
at(I const& i, Ks const&...ks)
-> decltype(m_map.at(i).at(ks...))
{
return m_map.at(i).at(ks...);
}
};
// -----------------------------------------------------------------------------
struct foo
{
std::string s;
int i;
char c;
operator std::string() const { return s; }
operator int () const { return i; }
operator char () const { return c; }
bool operator==(foo const& rhs) const
{
return s==rhs.s && i==rhs.i && c==rhs.c;
}
};
int main(int argc, char* argv[])
{
foo f1{ "f1", 1, 'z' };
foo f2{ "f2", 9, 'y' };
foo f3{ "f3", 3, 'x' };
foo f4{ "f1", 4, 'k' };
group_by<foo,std::string,int,char> gb;
gb.insert(&f1);
gb.insert(&f2);
gb.insert(&f3);
gb.insert(&f4);
std::string k1{ "f1" };
int k2{ 1 };
char k3{ 'z' };
auto& a = gb.at(k1).at(k2).at(k3).at(0);
auto& b = gb.at(k1).at(k2).m_map;
auto& c = gb.at(k1).m_map;
auto& d = gb.at(k1, k2).m_map;
auto& e = gb.at(k1, k2, k3).m_vec;
auto& f = gb.at(k1, k2, k3, 0);
assert(a==f1);
assert(b.size()==1);
assert(c.size()==2);
assert(d.size()==1);
assert(e.size()==1);
assert(f==f1);
return 0;
}
+1 tyvm - これを今すぐ試します – kfmfe04
これを試しましたか?それはコンパイルされていないようです... –
@AndyProwlあなたは正しい - 私はそれを動作させるためにそれを再生しなければならなかった。今すぐ掃除する。完了したらOPを更新します。彼の答えは、私がそれを働かせるのに十分だった。 – kfmfe04