Skip to content
Snippets Groups Projects
Commit ed72d969 authored by Andre Gunther's avatar Andre Gunther :island:
Browse files

Modernise CountIterator

parent b5d888da
No related branches found
No related tags found
1 merge request!4256Modernise CountIterator and apply it
Pipeline #6119354 passed
......@@ -10,6 +10,7 @@
\*****************************************************************************/
#include "Event/Track_v1.h"
#include "Event/TrackFunctor.h"
#include "Kernel/CountIterator.h"
#include "Kernel/TaggedBool.h"
#include "gsl/gsl_cdf.h"
#include <algorithm>
......@@ -244,25 +245,10 @@ namespace LHCb::Event {
//=============================================================================
// Count the number of LHCbIDs that two tracks have in common
//=============================================================================
namespace {
// inserter which only counts how often something is inserted
struct counting_inserter {
size_t count = 0;
counting_inserter& operator++() { return *this; } // nop
counting_inserter& operator*() { return *this; } // redirect to self, so that our op= is called
counting_inserter& operator=( const LHCbID& ) {
++count;
return *this;
} // raison d'etre
};
} // namespace
size_t Track::nCommonLhcbIDs( const Track& rhs ) const {
return std::set_intersection( begin( m_lhcbIDs ), end( m_lhcbIDs ), begin( rhs.m_lhcbIDs ), end( rhs.m_lhcbIDs ),
counting_inserter{} )
.count;
CountIterator{} )
.count();
}
//=============================================================================
......
......@@ -21,6 +21,7 @@
// local
#include "Event/TrackFunctor.h"
#include "Event/Track_v2.h"
#include "Kernel/CountIterator.h"
#include "Kernel/TaggedBool.h"
// ============================================================================
......@@ -40,18 +41,6 @@ namespace {
TrackFunctor::increasingByZ(), std::forward<F>( f ) );
}
// inserter which only counts how often something is inserted
struct counting_inserter {
size_t count = 0;
counting_inserter& operator++() { return *this; } // nop
counting_inserter& operator*() { return *this; } // redirect to self, so that our op= is called
template <typename T>
counting_inserter& operator=( T&& ) {
++count; // raison d'etre
return *this;
}
};
template <size_t N>
std::array<double, N + 1> generate_chi2max( double limit ) {
std::array<double, N + 1> c = {0};
......@@ -219,8 +208,8 @@ namespace LHCb::Event::v2 {
//=============================================================================
size_t Track::nCommonLhcbIDs( const Track& rhs ) const {
return std::set_intersection( begin( m_lhcbIDs ), end( m_lhcbIDs ), begin( rhs.m_lhcbIDs ), end( rhs.m_lhcbIDs ),
counting_inserter{} )
.count;
CountIterator{} )
.count();
}
//=============================================================================
......
/*****************************************************************************\
* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration *
* (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration *
* *
* This software is distributed under the terms of the GNU General Public *
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". *
......@@ -8,48 +8,54 @@
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\*****************************************************************************/
// ============================================================================
#ifndef KERNEL_COUNTITERATOR_H
#define KERNEL_COUNTITERATOR_H 1
// ============================================================================
// STD & STL
// ============================================================================
#include <iterator>
// ============================================================================
/** @class CountIterator CountIterator.h Kernel/CountIterator.h
* Trivial "count"-iterator: output iterator that only counts
*
* @author Vanya Belyaev
* @date 2015-03-17
*/
template <typename TYPE>
class count_iterator {
public:
// ========================================================================
/// Constructor
count_iterator() = default;
//
count_iterator& operator=( const TYPE& /* value */ ) {
++m_count;
return *this;
}
//
count_iterator& operator*() { return *this; }
count_iterator& operator++() { return *this; }
count_iterator& operator++( int ) { return *this; }
//
// ========================================================================
public:
// ==========================================================================
/// the the counter
[[nodiscard]] unsigned long count() const { return m_count; }
// ==========================================================================
private:
///
unsigned long m_count{0};
// ==========================================================================
};
// ============================================================================
// The END
// ============================================================================
#endif // KERNEL_COUNTITERATOR_H
#pragma once
#include <cstddef>
#include <functional>
#include <utility>
namespace LHCb {
namespace details {
struct AlwaysTrue {
template <typename T>
constexpr bool operator()( const T& ) const noexcept {
return true;
}
};
} // namespace details
/**
* @brief OutputIterator struct that increments a count when using the assignment operator and Predicate is true.
*
* @tparam Predicate
*
* @details Fulfills https://en.cppreference.com/w/cpp/named_req/OutputIterator
* and can be used e.g. in a std::set_intersection counting only elements fulfilling the predicate.
*/
template <typename Predicate>
class CountIfIterator {
std::size_t m_count{0};
Predicate m_predicate;
public:
explicit CountIfIterator( Predicate pred = {} ) : m_predicate{std::move( pred )} {}
CountIfIterator& operator++() { return *this; }
CountIfIterator& operator*() { return *this; }
template <typename T>
CountIfIterator& operator=( const T& data ) {
if ( std::invoke( m_predicate, data ) ) ++m_count;
return *this;
}
auto count() { return m_count; }
};
/**
* @brief OutputIterator struct that increments a count when using the assignment operator.
* @details Fulfills https://en.cppreference.com/w/cpp/named_req/OutputIterator
* and can be used e.g. in a std::set_intersection.
*/
using CountIterator = CountIfIterator<details::AlwaysTrue>;
} // namespace LHCb
......@@ -16,16 +16,24 @@
#include <vector>
BOOST_AUTO_TEST_CASE( test_count_iterator ) {
count_iterator<int> i;
using namespace LHCb;
auto i = CountIterator{};
BOOST_CHECK( i.count() == 0 );
std::vector<int> data = {0, 1, 2, 3, 4, 5, 6};
{
auto result = std::copy( begin( data ), end( data ), count_iterator<int>() );
auto result = std::copy( begin( data ), end( data ), CountIterator{} );
BOOST_CHECK( result.count() == 7 );
}
auto isNotEven = []( auto i ) { return i % 2; };
{
auto result = std::copy_if( begin( data ), end( data ), CountIterator{}, isNotEven );
BOOST_CHECK( result.count() == 3 );
}
auto j = CountIfIterator{isNotEven};
BOOST_CHECK( j.count() == 0 );
{
auto result = std::copy_if( begin( data ), end( data ), count_iterator<int>(), []( auto i ) { return i % 2; } );
auto result = std::copy( begin( data ), end( data ), j );
BOOST_CHECK( result.count() == 3 );
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment