Can I use std::accumulate with a fallible operation without exceptions? - c++

I have some operation that I would like to use with std::accumulate, but it may fail for some elements, in which case the accumulation should be aborted. With exceptions, I could throw an exception in case of failure, but I need to build without exceptions. With exceptions, this would look like this (the operation being greatly simplified):
std::optional<int> sum_accumulate_with_exceptions(
std::vector<int> const& aVec) {
try {
return std::accumulate(aVec.begin(), aVec.end(), 0,
[](int oldSum, int current) {
if (current > 42)
throw std::logic_error{"too large"};
return oldSum + current;
});
} catch (std::logic_error const&) {
return std::nullopt;
}
}
Actually, even with the possibility of using exceptions, this appears quite wasteful, as I am not interested in the particular exception thrown, and so the overhead of exceptions is unnecessarily large.
Using std::accumulate, I could use an error flag like this:
std::optional<int> sum_accumulate_without_exceptions(
std::vector<int> const& aVec) {
bool errored = false;
int res = std::accumulate(aVec.begin(), aVec.end(), 0,
[&errored](int oldSum, int current) {
if (errored) return 0;
if (current > 42) {
errored = true;
return 0;
}
return oldSum + current;
});
return errored ? std::optional<int>{} : res;
}
However, this is clearly bad, since this always iterates over the whole container, which might be large.
I came up with my own variant of std::accumulate:
template <typename It, typename T, typename Op>
std::optional<T> accumulate_shortcircuit(It aBegin, It aEnd, T aInit,
const Op& aOp) {
std::optional<T> res = std::move(aInit);
for (auto it = aBegin; it != aEnd; ++it) {
res = aOp(*res, *it);
if (!res) break;
}
return res;
}
This can be used nicely for the example case like this:
std::optional<int> sum_accumulate_shortcircuit(std::vector<int> const& aVec) {
return accumulate_shortcircuit(aVec.begin(), aVec.end(), 0,
[](int oldSum, int current) {
if (current > 42) {
return std::optional<int>{};
}
return std::optional<int>{oldSum + current};
});
}
However, I would prefer using std::accumulate (or any other standard library algorithm [edit:] or combination of them) itself, instead of using a replacement. Is there any way to achieve this?
While I was using C++17's std::optional in the example, ideally this would only use C++14 standard library algorithms, but I am also interested in solutions from newer/future standard versions.
[edit:] Based on #NathanOliver's answer, accumulate_shortcircuit could be implemented like this without having the range TS:
template <typename It, typename T, typename Op>
std::optional<T> accumulate_shortcircuit(It aBegin, It aEnd, T aInit,
const Op& aOp) {
std::optional<T> res = std::move(aInit);
std::all_of(aBegin, aEnd, [&](const T& element) {
return static_cast<bool>(res = aOp(*res, element));
});
return res;
}

You need an algorithm that has short circuiting built in. The first one that comes to to mind is std::any_of. You can use a lambda to do the sumation, and then return true to it once you've reached the point where you want to return. That would give you a function like
int sum_accumulate_shortcircuit(std::vector<int> const& aVec)
{
int sum = 0;
std::any_of(aVec.begin(), aVec.end(),
[&](auto elm) { if (elm > 42) return true; sum += elm; return false; });
return sum;
}

For future reference, this type of composition of algorithms/operations will be much easier in C++20 (with the inclusion of the ranges TS). This is an example from the current TS using accumulate and view::take_while:
auto sum = ranges::accumulate(my_vec | view::take_while([] (auto i) -> i <= 42), 0);

Related

Ways of defining accepted template parameter values

My program has a series of functions that take a template argument for an integer that needs to be known at compile time. The functions only accept a few possible values for this integer, and I am looking for a clean way to have a single place defining these options so the list can easily added or changed. Here is an example of how I am currently doing this.
template<int Dim>
float computeMinDist(float* data, int idx);
float computeMinDistSelect(float* data, int idx, int dim) {
if(dim <= 64) {
return computeMinDist<64>(data, idx);
}
else if(dim <= 100) {
return computeMinDist<100>(data, idx);
}
else {
printf("Dimension over 100 not supported.\n");
exit(1);
}
}
I have other functions that have the selected dimension parameter, and I would like to be able to define all of the options in one place. I've tried using a static constexpr arrays or enums to store the options, but can't get it to compile. Any advice would be great! Thanks.
You could create a table at compile time and binary search it for the specific value you get at runtime:
using table_pair = std::pair<int, float(*)(float*, int)>;
template <int... Dims>
constexpr auto make_table() {
auto arr = std::array<table_pair, sizeof...(Dims)>
{
table_pair{Dims, &computeMinDist<Dims>}...
};
// Can get rid of this sort if you can guarantee you always pass ordered Dims
std::sort(arr.begin(), arr.end(), [](auto& l, auto& r) {
return l.first < r.first;
});
return arr;
}
// Here you define all possible options.
constexpr auto table = make_table<64, 100>();
float computeMinDistSelect(float* data, int idx, int dim) {
auto it = std::lower_bound(
table.begin(), table.end(),
table_pair{dim, nullptr},
[](auto& l, auto& r) { return l.first < r.first; });
if (it == table.end()) {
printf("Dimension %d not supported.\n", dim);
exit(1);
}
return it->second(data, idx);
}
I return an array that we binary search since I assume your values seem to be pretty sparse. If your possible values are pretty dense, you can just return an array of function pointers with the invalid values having nullptr and index into the table directly.
https://godbolt.org/z/Yce355bP4

Express early termination with STL algorithms

I'm trying to rewrite some loops in my code as standard library functions. The following snippet seems to follow a general model for early termination and I'm wondering how to express that without explicit loops?
auto sum = 0;
for (const string& key : keys) {
if (my_map.find(key) == my_map.end())
return nullptr;
sum += my_map[key];
}
return make_unique<int>(sum);
Here's one possible approach: compute sum as the side-effect of an algorithm that terminates early. e.g.
int sum = 0;
auto f = std::find_if(keys.begin(), keys.end(), [&](string const &key) {
if (my_map.find(key) == my_map.end())
return true;
sum += my_map[key];
});
return f == keys.end() ? make_unique(sum) : nullptr;

C++ Bimap Left unordered_map Right sorted mutable multimap

I need to implement the following datastructure for my project. I have a relation of
const MyClass*
to
uint64_t
For every pointer I want to save a counter connected to it, which can be changed over time (in fact only incremented). This would be no problem, I could simply store it in a std::map. The problem is that I need fast access to the pointers which have the highest values.
That is why I came to the conclusion to use a boost::bimap. It is defined is follows for my project:
typedef boost::bimaps::bimap<
boost::bimaps::unordered_set_of< const MyClass* >,
boost::bimaps::multiset_of< uint64_t, std::greater<uint64_t> >
> MyBimap;
MyBimap bimap;
This would work fine, but am I right that I can not modify the uint64_t on pair which were inserted once? The documentation says that multiset_of is constant and therefore I cannot change a value of pair in the bimap.
What can I do? What would be the correct way to change the value of one key in this bimap? Or is there a simpler data structure possible for this problem?
Here's a simple hand-made solution.
Internally it keeps a map to store the counts indexed by object pointer, and a further multi-set of iterators, ordered by descending count of their pointees.
Whenever you modify a count, you must re-index. I have done this piecemeal, but you could do it as a batch update, depending on requirements.
Note that in c++17 there is a proposed splice operation for sets and maps, which would make the re-indexing extremely fast.
#include <map>
#include <set>
#include <vector>
struct MyClass { };
struct store
{
std::uint64_t add_value(MyClass* p, std::uint64_t count = 0)
{
add_index(_map.emplace(p, count).first);
return count;
}
std::uint64_t increment(MyClass* p)
{
auto it = _map.find(p);
if (it == std::end(_map)) {
// in this case, we'll create one - we could throw instead
return add_value(p, 1);
}
else {
remove_index(it);
++it->second;
add_index(it);
return it->second;
}
}
std::uint64_t query(MyClass* p) const {
auto it = _map.find(p);
if (it == std::end(_map)) {
// in this case, we'll create one - we could throw instead
return 0;
}
else {
return it->second;
}
}
std::vector<std::pair<MyClass*, std::uint64_t>> top_n(std::size_t n)
{
std::vector<std::pair<MyClass*, std::uint64_t>> result;
result.reserve(n);
for (auto idx = _value_index.begin(), idx_end = _value_index.end() ;
n && idx != idx_end ;
++idx, --n) {
result.emplace_back((*idx)->first, (*idx)->second);
}
return result;
}
private:
using map_type = std::map<MyClass*, std::uint64_t>;
struct by_count
{
bool operator()(map_type::const_iterator l, map_type::const_iterator r) const {
// note: greater than orders by descending count
return l->second > r->second;
}
};
using value_index_type = std::multiset<map_type::iterator, by_count>;
void add_index(map_type::iterator iter)
{
_value_index.emplace(iter->second, iter);
}
void remove_index(map_type::iterator iter)
{
for(auto range = _value_index.equal_range(iter);
range.first != range.second;
++range.first)
{
if (*range.first == iter) {
_value_index.erase(range.first);
return;
}
}
}
map_type _map;
value_index_type _value_index;
};

Elegant way to iterate conditionally forwards or reversed

I have to process an std::vector either forwards or in reverse, depending upon a boolean flag. What's the most elegant way to accomplish this? Before needing to do it in reverse I had:
BOOST_FOREACH(const CType &foo, vec) {
...
}
However, now I have the horrendous-looking:
for (int i=undoing ? (vec.size()-1) : 0; undoing ? (i >= 0) : (i < vec.size()); undoing ? (i--) : (i++)) {
const CType &foo = vec[i];
...
}
Is there a better way?
I don't know that people would call it elegant, but there's:
auto do_it = [](const CType& elem)
{
...
};
if (iterate_forward) {
std::for_each(vec.begin(), vec.end(), do_it);
}
else {
std::for_each(vec.rbegin(), vec.rend(), do_it);
}
Add a template function that works with either the forward iterators or reverse iterators. Call the function using the appropriate iterator based on the value of undoing.
template <typename Iterator>
void doStuff(Iterator iter, Iterator end)
{
for ( ; iter != end; ++iter )
{
// Do stuff
}
}
if ( undoing )
{
doStuff(vec.rbegin(), vec.rend());
}
else
{
doStuff(vec.begin(), vec.end());
}
How about keeping the loop running as it is from 0 to vector.size, but reading the array in the direction you need.
int idx;
for (int i =0; i < vec.size(); i ++)
{
if (undoing) // assuming going forward
idx = i;
else // going backwards
idx = vec.size() - i - 1;
const CType &foo = vec[idx];
}
You may also use Boost.Range-based solution. It's similar to the one using STL algorithms, already proposed.
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/algorithm/for_each.hpp>
// In C++11 lambda expression can be used instead
struct my_fun
{
void operator()(const CType& elem) const
{
/*...*/
}
};
/*...*/
using namespace boost::adaptors;
if ( iterate_forward )
boost::for_each(my_vect, my_fun());
else
boost::for_each(my_vect | reversed, my_fun());

How do I efficiently remove_if only a single element from a forward_list?

Well I think the question pretty much sums it up. I have a forward_list of unique items, and want to remove a single item from it:
std::forward_list<T> mylist;
// fill with stuff
mylist.remove_if([](T const& value)
{
return value == condition;
});
I mean, this method works fine but it's inefficient because it continues to search once the item is found and deleted. Is there a better way or do I need to do it manually?
If you only want to remove the first match, you can use std::adjacent_find followed by the member erase_after
#include <algorithm>
#include <cassert>
#include <forward_list>
#include <iostream>
#include <ios>
#include <iterator>
// returns an iterator before first element equal to value, or last if no such element is present
// pre-condition: before_first is incrementable and not equal to last
template<class FwdIt, class T>
FwdIt find_before(FwdIt before_first, FwdIt last, T const& value)
{
assert(before_first != last);
auto first = std::next(before_first);
if (first == last) return last;
if (*first == value) return before_first;
return std::adjacent_find(first, last, [&](auto const&, auto const& R) {
return R == value;
});
}
int main()
{
auto e = std::forward_list<int>{};
std::cout << std::boolalpha << (++e.before_begin() == end(e)) << "\n";
std::cout << (find_before(e.before_begin(), end(e), 0) == end(e)) << "\n";
auto s = std::forward_list<int>{ 0 };
std::cout << (find_before(s.before_begin(), end(s), 0) == s.before_begin()) << "\n";
auto d = std::forward_list<int>{ 0, 1 };
std::cout << (find_before(d.before_begin(), end(d), 0) == d.before_begin()) << "\n";
std::cout << (find_before(d.before_begin(), end(d), 1) == begin(d)) << "\n";
std::cout << (find_before(d.before_begin(), end(d), 2) == end(d)) << "\n";
// erase after
auto m = std::forward_list<int>{ 1, 2, 3, 4, 1, 3, 5 };
auto it = find_before(m.before_begin(), end(m), 3);
if (it != end(m))
m.erase_after(it);
std::copy(begin(m), end(m), std::ostream_iterator<int>(std::cout, ","));
}
Live Example
This will stop as soon as a match is found. Note that the adjacent_find takes a binary predicate, and by comparing only the second argument, we get an iterator before the element we want to remove, so that erase_after can actually remove it. Complexity is O(N) so you won't get it more efficient than this.
FWIW, here's another short version
template< typename T, class Allocator, class Predicate >
bool remove_first_if( std::forward_list< T, Allocator >& list, Predicate pred )
{
auto oit = list.before_begin(), it = std::next( oit );
while( it != list.end() ) {
if( pred( *it ) ) { list.erase_after( oit ); return true; }
oit = it++;
}
return false;
}
Going to have to roll your own...
template <typename Container, typename Predicate>
void remove_first_of(Container& container, Predicate p)
{
auto it = container.before_begin();
for (auto nit = std::next(it); ; it = nit, nit = std::next(it))
{
if (nit == container.end())
return;
if (p(*nit))
{
container.erase_after(it);
return;
}
}
}
A more complete example...
There is nothing in the standard library which would be directly applicable. Actually, there is. See #TemplateRex's answer for that.
You can also write this yourself (especially if you want to combine the search with the erasure), something like this:
template <class T, class Allocator, class Predicate>
bool remove_first_if(std::forward_list<T, Allocator> &list, Predicate pred)
{
auto itErase = list.before_begin();
auto itFind = list.begin();
const auto itEnd = list.end();
while (itFind != itEnd) {
if (pred(*itFind)) {
list.erase_after(itErase);
return true;
} else {
++itErase;
++itFind;
}
}
return false;
}
This kind of stuff used to be a standard exercise when I learned programming way back in the early '80s. It might be interesting to to recall the solution, and compare that with what one can do in C++. Actually that was in Algol 68, but I won't impose that on you and give the translation into C. Given
typedef ... T;
typedef struct node *link;
struct node { link next; T data; };
one could write, realising that one needs to pass the address of the list head pointer if is to be possible to unlink the first node:
void search_and_destroy(link *p_addr, T y)
{
while (*p_addr!=NULL && (*p_addr)->data!=y)
p_addr = &(*p_addr)->next;
if (*p_addr!=NULL)
{
link old = *p_addr;
*p_addr = old->next; /* unlink node */
free(old); /* and free memory */
}
}
There are a lot of occurrences of *p_addr there; it is the last one, where it is the LHS of an assignment, that is the reason one needs the address of a pointer here in the first place. Note that in spite of the apparent complication, the statement p_addr = &(*p_addr)->next; is just replacing a pointer by the value it points to, and then adding an offset (which is 0 here).
One could introduce an auxiliary pointer value to lighten the code a bit up, as follows
void search_and_destroy(link *p_addr, T y)
{
link p=*p_addr;
while (p!=NULL && p->data!=y)
p=*(p_addr = &p->next);
if (p!=NULL)
{
*p_addr = p->next;
free(p);
}
}
but that is fundamentally the same code: any decent compiler should realise that the pointer value *p_addr is used multiple times in succession in the first example, and keep it in a register.
Now with std::forward_list<T>, we are not allowed access to the pointers that link the nodes, and get those awkward "iterators pointing one node before the real action" instead. Our solution becomes
void search_and_destroy(std::forward_list<T> list, T y)
{
std::forward_list<T>::iterator it = list.before_begin();
const std::forward_list<T>::iterator NIL = list.end();
while (std::next(it)!=NIL && *std::next(it)!=y)
++it;
if (std::next(it)!=NIL)
list.erase_after(it);
}
Again we could keep a second iterator variable to hold std::next(it) without having to spell it out each time (not forgetting to refresh its value when we increment it) and arrive at essentially the answer by Daniel Frey. (We could instead try to make that variable a pointer of type *T equal to &*std::next(it) instead, which suffices for the use we make of it, but it would actually be a bit of a hassle to ensure it becomes the null pointer when std::next(it)==NIL, as the standard will not let us take &*NIL).
I cannot help feel that since the old days the solution to this problem has not become more elegant.