यहाँ एक त्वरित अपेक्षाकृत न्यूनतम है filter
कार्य है।
यह एक विधेय लेता है। यह एक फ़ंक्शन ऑब्जेक्ट देता है जो एक पुनरावृत्ति लेता है।
यह एक पुनरावृत्ति देता है जिसका उपयोग for(:)
लूप में किया जा सकता है ।
template<class It>
struct range_t {
It b, e;
It begin() const { return b; }
It end() const { return e; }
bool empty() const { return begin()==end(); }
};
template<class It>
range_t<It> range( It b, It e ) { return {std::move(b), std::move(e)}; }
template<class It, class F>
struct filter_helper:range_t<It> {
F f;
void advance() {
while(true) {
(range_t<It>&)*this = range( std::next(this->begin()), this->end() );
if (this->empty())
return;
if (f(*this->begin()))
return;
}
}
filter_helper(range_t<It> r, F fin):
range_t<It>(r), f(std::move(fin))
{
while(true)
{
if (this->empty()) return;
if (f(*this->begin())) return;
(range_t<It>&)*this = range( std::next(this->begin()), this->end() );
}
}
};
template<class It, class F>
struct filter_psuedo_iterator {
using iterator_category=std::input_iterator_tag;
filter_helper<It, F>* helper = nullptr;
bool m_is_end = true;
bool is_end() const {
return m_is_end || !helper || helper->empty();
}
void operator++() {
helper->advance();
}
typename std::iterator_traits<It>::reference
operator*() const {
return *(helper->begin());
}
It base() const {
if (!helper) return {};
if (is_end()) return helper->end();
return helper->begin();
}
friend bool operator==(filter_psuedo_iterator const& lhs, filter_psuedo_iterator const& rhs) {
if (lhs.is_end() && rhs.is_end()) return true;
if (lhs.is_end() || rhs.is_end()) return false;
return lhs.helper->begin() == rhs.helper->begin();
}
friend bool operator!=(filter_psuedo_iterator const& lhs, filter_psuedo_iterator const& rhs) {
return !(lhs==rhs);
}
};
template<class It, class F>
struct filter_range:
private filter_helper<It, F>,
range_t<filter_psuedo_iterator<It, F>>
{
using helper=filter_helper<It, F>;
using range=range_t<filter_psuedo_iterator<It, F>>;
using range::begin; using range::end; using range::empty;
filter_range( range_t<It> r, F f ):
helper{{r}, std::forward<F>(f)},
range{ {this, false}, {this, true} }
{}
};
template<class F>
auto filter( F&& f ) {
return [f=std::forward<F>(f)](auto&& r)
{
using std::begin; using std::end;
using iterator = decltype(begin(r));
return filter_range<iterator, std::decay_t<decltype(f)>>{
range(begin(r), end(r)), f
};
};
};
मैंने शॉर्ट कट लिया। एक वास्तविक पुस्तकालय को वास्तविक for(:)
पुनरावृत्तियों को बनाना चाहिए, न कि -क्वालिफ़ाइंग छद्म-फासिड्स जो मैंने किए।
उपयोग के बिंदु पर, यह इस तरह दिखता है:
int main()
{
std::vector<int> test = {1,2,3,4,5};
for( auto i: filter([](auto x){return x%2;})( test ) )
std::cout << i << '\n';
}
जो बहुत अच्छा है, और प्रिंट
1
3
5
जीवंत उदाहरण ।
C ++ का प्रस्तावित जोड़ है जिसे Rangesv3 कहा जाता है जो इस तरह की बात करता है और बहुत कुछ करता है। boost
इसमें फिल्टर रेंज / पुनरावृत्त भी उपलब्ध हैं। बूस्ट में मददगार भी होते हैं जो ऊपर लिखे को बहुत कम लिखते हैं।
std::copy_if
, लेकिन चयन आलसी नहीं हैं