SQL adlarını kullanan group_by
adlı yinelemeli bir harita sınıfında çalışıyorum. ÖrneğinZincirleme yöntem çağrılarının yerini alan değişken bir yöntem nasıl yazılır?
, gb bu sırayla, std::string
, int
ve char
kilit türlerine göre gruplandırılmış foo
işaretçiler depolayacak bir group_by
amacıdır.
group_by<foo,std::string,int,char> gb;
group_by
akım seviyesi haritası içine bakmak için kullanılabilecek bir at(I const& key)
erişimci yöntem sağlar. at()
numaralı zincirleme, daha derin haritaların alınmasını gerektiriyor.
auto& v = gb.at(k1).at(k2).at(k3).get_vec();
SORUN
Ben zincirleme olmadan bir çağrıda daha derin Haritalar hizmetini alabilirat_variadic(Args const& ...args)
denilen
at()
bir alternatif yaratmak istiyoruz
.
auto& w = gb.at_variadic(k1, k2);
auto& x = gb.at_variadic(k1, k2, k3);
Ancak, bazı sorunlarla çalıştırıyorum. Her şeyden önce, dönüş türünü nasıl tanımlayacağımı bilmiyorum, çünkü değişken değişkenlere bağlı. Belki bir şekilde decltype()
kullanın?
ÇALIŞMA CEVAP
Ecatmur's answer below iyi bir yaklaşım ortaya koydu.
Derleyiciyi mutlu etmek için group_by<>
terminal durumu ile uğraşmak zorunda kaldım, ancak Ecatmur'un yanıtını esas alan aşağıdaki kod gcc 4.7.2 ile iyi çalışıyor gibi görünüyor.
#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 - şimdi bunu deneyeceğim – kfmfe04
Bunu denediniz mi? Bu derleme görünmüyor ... –
@AndyProwl haklısın - Çalışmak için onunla oynamak zorunda kaldım. Şimdi temizliyorum. İşlem tamamlandığında OP'yi günceller. Cevabı, çalışmam için yeterliydi. – kfmfe04