मैं group_by
नामक रिकर्सिव मैप क्लास पर काम कर रहा हूं जो एसक्यूएल नेमकेक मॉडल करता है।एक वैरिएड विधि कैसे लिखें जो जंजीर विधि कॉल को प्रतिस्थापित करता है?
उदाहरण के लिए, जीबी एक group_by
वस्तु जो इसी क्रम में std::string
, int
, और char
कुंजी प्रकार के आधार पर वर्गीकृत foo
की ओर इशारा संग्रहीत करेगा है।
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();
समस्या
मैं चेनिंग बिना, at_variadic(Args const& ...args)
बुलाया at()
का एक वैकल्पिक जो एक कॉल में गहरी नक्शे प्राप्त कर सकते हैं सब बनाना चाहेंगे।
auto& w = gb.at_variadic(k1, k2);
auto& x = gb.at_variadic(k1, k2, k3);
हालांकि, मैं कुछ मुद्दों में भाग रहा हूं। सबसे पहले, मुझे नहीं पता कि वापसी प्रकार कैसे निर्दिष्ट करें, क्योंकि यह विविध तर्कों पर निर्भर करता है। शायद decltype()
का उपयोग करें, किसी भी तरह?
काम उत्तर
Ecatmur's answer below एक अच्छा दृष्टिकोण को रेखांकित किया।
मुझे कंपाइलर को खुश करने के लिए group_by<>
के टर्मिनल केस के साथ खेलना पड़ा, लेकिन नीचे दिया गया कोड, इक्टामूर के उत्तर पर आधारित, जीसीसी 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 आप सही हैं - मुझे इसे काम करने के लिए इसके साथ खेलना पड़ा। इसे अभी साफ करो। पूरा होने पर ओपी अपडेट होगा। उसका जवाब मेरे लिए काम करने के लिए पर्याप्त था। – kfmfe04