functor returning 0 - c++

I've recently started teaching myself the standard template library. I was curious as to why the GetTotal() method in this class is returning 0?
...
class Count
{
public:
Count() : total(0){}
void operator() (int val){ total += val;}
int GetTotal() { return total;}
private:
int total;
};
void main()
{
set<int> s;
Count c;
for(int i = 0; i < 10; i++) s.insert(i);
for_each(s.begin(), s.end(), c);
cout << c.GetTotal() << endl;
}

for_each takes the function by-value. That is, it uses a copy of the functor and not the functor itself. Your local c is left unchanged.
for_each returns the functor it used, though, so you could do:
Count c;
c = for_each(s.begin(), s.end(), c);
Or more idiomatically:
Count c = for_each(s.begin(), s.end(), Count());
However, there exists such functionality already (no need for your functor):
int total = std::accumulate(s.begin(), s.end(), 0);

Related

How to compose generators with STL algorithms

I have an algorithm which generates combinations from entries of a container and I want to find the combination which minimizes a cost function:
struct Vec { double x; double y; };
double cost( Vec a, Vec b ) {
double dx = a.x - b.x;
double dy = a.y - b.y;
return dx*dx + dy*dy;
}
pair<Vec,Vec> get_pair_with_minimum_cost ( vector<Vec> inp, double (*cost_fun)(Vec,Vec) )
{
pair<Vec,Vec> result;
double min_cost = FLT_MAX;
size_t sz = inp.size();
for(size_t i=0; i<sz; i++) {
for (size_t j=i; j<sz; j++) {
double cost = cost_fun(inp[i], inp[j]);
if (cost < min_cost) {
min_cost = cost;
result = make_pair(inp[i], inp[j]);
}
}
}
return result;
}
vector <Vec> inp = {....};
auto best_pair = get_pair_with_minimum_cost ( inp, cost );
Unfortunately, get_pair_with_minimum_cost() does 2 jobs:
generates the combinations
gets the minimum element
I could break them in two functions, like:
the generator:
template <class Func>
void generate_all_combinations_of( vector<Vec> inp, Func fun )
{
size_t sz = inp.size();
for(size_t i=0; i<sz; i++) {
for (size_t j=i; j<sz; j++) {
fun(make_pair(inp[i], inp[j]));
}
}
}
and then use std::min_element on the output of the generator, i.e.
vector<Vec> inp = {....};
vector<pair<Vec,Vec>> all_combinations;
generate_all_combinations_of(inp, [&](vector<pair<Vec,Vec>> o){all_combinations.push_back(o); } );
auto best_pair = *min_element(all_combinations.begin(), all_combinations.end(), cost);
but I do not want the pay the cost of creating and extra container with temporary data (all_combinations).
Questions:
Can I rewrite the generate_all_combinations_of() such that it uses yield or the new std::ranges in such a way that I can combine it with STL algorithms such as find_if, any_of, min_element or even adjacent_pair ?
The great thing about this 'generator' function is that it is easy to read, so I would like to keep it as readable as possible.
NB: some of these algorithms need to break the loop.
What is the official name of combining entries this way?
It this the combinations used in 'bubble-sort'.
Here's how I would write the function in c++20, using range views and algorithms so that there isn't a separate container that stores the intermediate results:
double get_minimum_cost(auto const & inp)
{
namespace rs = std::ranges;
namespace rv = std::ranges::views;
// for each i compute the minimum cost for all j's
auto min_cost_from_i = [&](auto i)
{
auto costs_from_i = rv::iota(i + 1, inp.size())
| rv::transform([&](auto j)
{
return cost(inp[i], inp[j]);
});
return *rs::min_element(costs_from_i);
};
// compute min costs for all i's
auto all_costs = rv::iota(0u, inp.size())
| rv::transform(min_cost_from_i);
return *rs::min_element(all_costs);
}
Here's a demo.
Note that the solution doesn't compare the cost between same elements, since the cost function example you showed would have a trivial result of 0. For a cost function that doesn't return 0, you can adapt the solution to generate a range from i instead of i + 1. Also, if the cost function is not symmetric, make that range start from 0 instead of i.
Also, this function has UB if you call it with an empty range, so you should check for that as well.
There is http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2168r0.pdf who's development I would follow
If you are using MSVC, and can use their experimental/generator (not sure if others support it yet), you can use
std::experimental::generator<std::size_t> Generate(std::size_t const end){
for(std::size_t i = 0; i < end; ++i)
co_yield i;
}
int main(){
auto vals = Generate(22);
auto const result = *std::min_element(std::begin(vals),std::end(vals));
std::cout <<'\n' << " " << result;
}
Here you would need to modify the Generate function to Yield a pair/or to yield cost
(My recommendation would be to Keep things simple and yield the cost)
Then use vals to find min_cost
Ranges
Based on what I can find about the Ranges Proposal, it works on the basis of std::begin and std::end both of which experimental::generator provides
So it should probably work
Here's how I would write the function in c++17, using algorithms' min_element function, with no need for a separate container that stores the intermediate results. I know you were looking for a c++20 solution, but this code does work fine under c++20, and perhaps it gives you some ideas about adapting functions to ranges when the range isn't just one of the ranges supplied by c++20's ranges library.
// TwoContainerRanger is an iterable container where the iterator consists
// of two indices that match the given filter, and whose iterators, when
// dereferenced, return the result of calling func with the
// elements of the two containers, at those two indices.
// filter can be nullptr.
template <typename Container1, typename Container2, typename Func>
struct TwoContainerRanger {
Container1 &c1;
Container2 &c2;
const Func &fun;
bool (*restriction)(size_t i1, size_t i2);
TwoContainerRanger(Container1 &container1, Container2 &container2,
bool (*filter)(size_t i1, size_t i2), const Func &func)
: c1(container1), c2(container2), fun(func), restriction(filter) {}
struct Iterator {
const TwoContainerRanger *gen;
size_t index1, index2;
auto &operator++() {
do {
if (++index1 == gen->c1.size()) {
if (++index2 == gen->c2.size()) {
// we leave both indices pointing to the end
// to indicate that we have reached the end.
return *this;
} else {
index1 = 0u;
}
}
} while (gen->restriction && gen->restriction(index1, index2) == false);
return *this;
}
bool operator==(const Iterator &other) const = default;
bool operator!=(const Iterator &other) const = default;
auto operator*() const {
return gen->fun(gen->c1[index1], gen->c2[index2]);
}
};
Iterator begin() {
Iterator b{this, size_t(0) - 1, 0u};
return ++b; // automatically applies the restriction
}
Iterator end() { return Iterator{this, c1.size(), c2.size()}; }
};
Calling it looks like this:
int main() {
std::array<Vec, 5> ar = {Vec{0, 0}, Vec{1, 1}, Vec{3, 3}, Vec{7, 7},
Vec{3.1, 3.1}};
TwoContainerRanger tcr{ar, ar, Triangle, cost};
auto result = std::min_element(tcr.begin(), tcr.end());
std::cout << "Min was at (" << result.index1 << "," << result.index2
<< "); cost was " << *result << '\n';
}
Here's a demo.

C++ Abstract Classes and Inheritance

I have this problem I'm trying to solve. Basically the base class has the function map, which takes a vector as input and outputs the final vector after some mapping function, in this case - f, has been performed. However, I'm really lost as to why when I print out 2*testVector - test1 in the main function, I get proper output, i.e. 6, -182 etc... but when I print out 2*testVector - test 2, it's still the same vector.
This happens both when I create "DoubleElements" twice or just call the same "DoubleElements" pointer twice (it only ever performs 1 map). Am I fundamentally missing some understanding? Any help is appreciated!
#include <iostream>
#include <vector>
using namespace std;
class RecursiveBase {
public:
vector<int> map(vector<int> baseVector) {
static int iter = 0;
// Base case, return the final vector.
if (iter == 5) {
return baseVector;
// Replace the element with the old element mapped to the function.
} else {
baseVector[iter] = this->f(baseVector[iter]);
iter++;
return map(baseVector);
}
}
private:
virtual int f(int value) = 0;
};
class DoubleElements: public RecursiveBase {
private:
int f(int value) {
return 3*value;
}
};
int main() {
vector<int> testVector, o1, o2;
testVector.push_back(3);
testVector.push_back(-91);
testVector.push_back(-42);
testVector.push_back(-16);
testVector.push_back(13);
DoubleElements de;
DoubleElements de1;
RecursiveBase *test1 = &de;
RecursiveBase *test2 = &de1;
o1 = test1->map(testVector);
o2 = test2->map(testVector);
std::cout << "2*testVector - test1" << std::endl;
for (unsigned int iter = 0; iter < o1.size(); iter++) {
std::cout << o1[iter] << std::endl;
}
std::cout << "2*testVector - test2" << std::endl;
for (unsigned int iter = 0; iter < o2.size(); iter++) {
std::cout << o2[iter] << std::endl;
}
}
static int iter = 0;
You should avoid declaring local static variables in methods unless 100% necessary.
The first call will increment iter to 5, but on the next call, iter, since it's static, will not reset it's value to 0.
As an example, a simple program like:
void test()
{
static int x = 0;
++x;
cout << x << endl;
}
int main()
{
test();
test();
return 0;
}
Will output
1
2
From class.static.data/1:
A static data member is not part of the subobjects of a class.
For iter is static. It is part of the class RecursiveBase NOT part of the RecursiveBase objects.
To fix it, reset iter to 0:
if (iter == 5) {
iter = 0; // reset iter
return baseVector;
}
OUTPUT
2*testVector - test1
9
-273
-126
-48
39
2*testVector - test2
9
-273
-126
-48
39
You can only ever call RecursiveBase::map once as it stands, because the iter is static. You also assume that you will only ever call it with a 5 element std::vector<int>, at which point std::array<int, 5> is a better choice.
If you want a recursive solution, instead pass the index as an additional parameter
public:
std::vector<int> map(std::vector<int> vec) {
return do_map(vec, 0);
}
private:
std::vector<int> do_map(std::vector<int> & vec, std::size_t index) {
if (index == vec.size()) { return vec; }
vec[index] = f(vec[index]);
return do_map(vec, ++index);
}
But that's still a gratuitous use of recursion. A much better solution is
public:
std::vector<int> map(std::vector<int> vec) {
std::transform(vec.begin(), vec.end(), vec.begin(), [this](int i) { return f(i); });
return vec;
}
You also have superfluous RecursiveBase * in your main
int main() {
std::vector<int> testVector{3, -91, -42, -16, 13};
DoubleElements de;
DoubleElements de1;
// declare at point of initialisation
// don't need ->
auto o1 = de.map(testVector);
auto o2 = de1.map(testVector);
std::cout << "2*testVector - test1" << std::endl;
for (unsigned int iter = 0; iter < o1.size(); iter++) {
std::cout << o1[iter] << std::endl;
}
std::cout << "2*testVector - test2" << std::endl;
for (unsigned int iter = 0; iter < o2.size(); iter++) {
std::cout << o2[iter] << std::endl;
}
return 0;
}

C++ List showing last 3 items from table

Hey i have a table of teams with the names and the points they have and i'm trying to figure out how to display the last 3 teams with the least amount of points in the table?
It displays all the teams and i want it to display only the last 3 in the table but don't know what way to go about it.
These are my Accessors
string GetName
int GetPoints
int lowest = 1000;
for (int i = 0; i < numTeams; i++)
{
if (league[i].GetPoints() < lowest)
{
lowest = league[i].GetPoints();
}
}
for (int i = 0; i < numTeams; i++)
{
if (league[i].GetPoints() == lowest)
{
cout << "\tThe lowest goals against is: " << league[i].GetName() << endl;
}
}
Actually, you don't need variable lowest, if you would sort the data before printing.
#include <algorithm>
// Sort using a Lambda expression.
std::sort(std::begin(league), std::end(league), [](const League &a, const League &b) {
return a.GetPoints() < b.GetPoints();
});
int last = 3;
for (int i = 0; i < last; i++)
{
cout << "\tThe lowest goals against is: " << league[i].GetName() << endl;
}
U could probably start by sorting your array
#include <algorithm>
std::array<int> foo;
std::sort(foo.begin(), foo.end());
and then Iterate From Your Last Element to your Last - 3. (U can use Reverse Iterators)
for (std::vector<int>::reverse_iterator it = v.rend() ; it != v.rend() + 3;
it++) {
//Do something
}
or by using auto
for (auto it = v.rend() ; it != v.rend() + 3; ++it) {
//Do something
}
In my example I've created test class(TestTeam) to implement several important methods for objects in your task.
I use std::sort method to sort container of objects, by default std::sort compares objects by less(<) operation, so I have overrided operator < for TestTeam object
bool operator < ( const TestTeam& r) const
{
return GetPoints() < r.GetPoints();
}
Also we could pass as third parameter another compare method or lambda method as shown in below answers:
std::sort(VecTeam.begin(), VecTeam.end(), [](const TestTeam& l, const TestTeam& r)
{
return l.GetPoints() < r.GetPoints();
});
And example when we use global method to compare:
bool CompareTestTeamLess(const TestTeam& l, const TestTeam& r)
{
return l.GetPoints() < r.GetPoints();
}
//...
// some code
//...
// In main() we use global method to sort
std::sort(VecTeam.begin(), VecTeam.end(), ::CompareTestTeamLess);
You can try my code with vector as container:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
// Test class for example
class TestTeam
{
public:
TestTeam(int16_t p, const std::string& name = "Empty name"):mPoints(p), mName(name)
{
};
int16_t GetPoints() const {return mPoints;}
const std::string& GetName() const {return mName;}
void SetName( const std::string& name ) {mName=name;}
bool operator < ( const TestTeam& r) const
{
return GetPoints() < r.GetPoints();
}
private:
int16_t mPoints;
std::string mName;
};
int main(int argc, const char * argv[])
{
const uint32_t COUNT_LOWEST_ELEMENTS_TO_FIND = 3;
// Fill container by test data with a help of non-explicit constructor to solve your task
std::vector<TestTeam> VecTeam {3,5,8,9,11,2,14,7};
// Here you can do others manipulations with team data ...
//Sort vector by GetPoints overloaded in less operator. After sort first three elements will be with lowest points in container
std::sort(VecTeam.begin(), VecTeam.end());
//Print results as points - name
std::for_each( VecTeam.begin(), VecTeam.begin() + COUNT_LOWEST_ELEMENTS_TO_FIND, [] (TestTeam el)
{
std::cout << el.GetPoints() << " - " << el.GetName() << std::endl;
} );
}
I made test class TestTeam only to implement test logic for your object.
If you try launch the program you can get next results:
2 - Empty name
3 - Empty name
5 - Empty name
Program ended with exit code: 0

About modifying the parameter of a functor

I have the following comparator for string objects
struct Comparator{
int x;
bool operator() (string a, string b) {
int i = 1;
if(a < b) {
i = -1;
}
i*= x;
if(i==-1) {
return true;
}
return false;
}
};
As you can see, it has a parameter x. when it is = 1 the comparison of strings is normal and when it is =-1 the comparison is inverted.
When using it in a method like sort for vector elements I can give the object instance of this comparator with the right x, but when I want to give this comparator to a template class like set, I need to give a class and not an object instance. So the only solution I see is to make x static. Is there a better solution?
Here is the example of a main where I would like to use this comparator:
int main(int argc, char** argv)
{
vector<string> vec;
vec.push_back("c");
vec.push_back("a");
vec.push_back("b");
Comparator comp;
comp.x = 1; // for normal comparison
comp.x = -1; // for inverse comparison
sort(vec.begin(),vec.end(), comp); // here I can give the functor instance
for(vector<string>::iterator it = vec.begin() ; it != vec.end(); it++)
{
cout << *it << endl;
}
set<string, Comparator> ss; // but here I must give the name of the functor class
ss.insert("c");
ss.insert("a");
ss.insert("b");
for(set<string>::iterator it = ss.begin() ; it != ss.end(); it++)
{
cout << *it << endl;
}
return 0;
}
All the relevant constructors of set also take an instance of Comp class.
set<string, Comparator> ss(Comparator(-1));
Now you only need a constructor for Comparator that initializes its member x with an appropriate value.
That said, the standard library already comes with a comparator class for this purpose:
set<string, std::greater<std::string> > ss;
That will not work: a < b does not(!) mean b < a.
You might utilize std::string::compare:
bool operator() (const std::string& a, const std::string& b) {
int result = a.compare(b) * x;
return result < 0;
}

how to use boost::unordered_map

for my application, i need to use a hash map, so i have written a test program in which i store some instances of a baseclass in a boost::unordered_map. but i want to reach the instances by calling special functions which return a derived class of the base and i use those functions' parameters for hash key of unordered_map. if no class is found with certain parameters then a class is generated and stored in map. the purpose of the program may not be clear but here is the code.
#include <boost/unordered_map.hpp>
#include <iostream>
using namespace std;
using namespace boost;
typedef unsigned char BYT;
typedef unsigned long long ULL;
class BaseClass
{
public:
int sign;
size_t HASHCODE;
BaseClass(){}
};
class ClassA : public BaseClass
{
public:
int AParam1;
int AParam2;
ClassA(int s1, int s2) : AParam1(s1), AParam2(s2)
{
sign = AParam1;
}
};
struct HashKey
{
ULL * hasharray;
size_t hashNum;
size_t HASHCODE;
HashKey(ULL * ULLarray, size_t Hashnum) : hasharray(ULLarray), hashNum(Hashnum), HASHCODE(0)
{ }
bool operator == (const HashKey & hk ) const
{
bool deg = (hashNum == hk.hashNum);
if (deg)
{
for (int i = 0; i< hashNum;i++)
if(hasharray[i] != hk.hasharray[i]) return false;
}
return deg;
}
};
struct ihash : std::unary_function<HashKey, std::size_t>
{
std::size_t operator()(HashKey const & x) const
{
std::size_t seed = 0;
if (x.hashNum == 1)
seed = x.hasharray[0];
else
{
int amount = x.hashNum * 8;
const std::size_t fnv_prime = 16777619u;
BYT * byt = (BYT*)x.hasharray;
for (int i = 0; i< amount;i++)
{
seed ^= byt[0];
seed *= fnv_prime;
}
}
return seed;
}
};
typedef std::pair<HashKey,BaseClass*> HashPair;
unordered_map<HashKey,BaseClass*,ihash> UMAP;
typedef unordered_map<HashKey,BaseClass*,ihash>::iterator iter;
BaseClass * & FindClass(ULL* byt, int Num, size_t & HCode)
{
HashKey hk(byt,Num);
HashPair hp(hk,0);
std::pair<iter,bool> xx = UMAP.insert(hp);
// if (xx.second) UMAP.rehash((UMAP.size() + 1) / UMAP.max_load_factor() + 1);
if (!xx.first->second) HCode = UMAP.hash_function()(hk);
return xx.first->second;
}
template <typename T, class A,class B>
T* GetClass(size_t& hashcode ,A a, B b)
{
ULL byt[3] = {a,b,hashcode};
BaseClass *& cls = FindClass(byt, 3, hashcode);
if(! cls){ cls = new T(a,b); cls->HASHCODE = hashcode;}
return static_cast<T*>(cls);
}
ClassA * findA(int Period1, int Period2)
{
size_t classID = 100;
return GetClass<ClassA>(classID,Period1,Period2);
}
int main(int argc, char* argv[])
{
int limit = 1000;
int modnum = 40;
int result = 0;
for(int i = 0 ; i < limit; i++ )
{
result += findA( rand() % modnum ,4)->sign ;
}
cout << UMAP.size() << "," << UMAP.bucket_count() << "," << result << endl;
int x = 0;
for(iter it = UMAP.begin(); it != UMAP.end(); it++)
{
cout << ++x << "," << it->second->HASHCODE << "," << it->second->sign << endl ;
delete it->second;
}
return 0;
}
the problem is, i expect that the size of UMAP is equal to modnum however it is allways greater than modnum which means there are more than one instance that has the same parameters and HASHCODE.
what is the solution to my problem? please help.
thanks
Here are a couple of design problems:
struct HashKey
{
ULL * hasharray;
...
Your key type stores a pointer to some array. But this pointer is initialized with the address of a local object:
BaseClass * & FindClass(ULL* byt, int Num, size_t & HCode)
{
HashKey hk(byt,Num); // <-- !!!
HashPair hp(hk,0);
std::pair<iter,bool> xx = UMAP.insert(hp);
if (!xx.first->second) HCode = UMAP.hash_function()(hk);
return xx.first->second;
}
template <typename T, class A,class B>
T* GetClass(size_t& hashcode ,A a, B b)
{
ULL byt[3] = {a,b,hashcode}; // <-- !!!
BaseClass *& cls = FindClass(byt, 3, hashcode);
if(! cls){ cls = new T(a,b); cls->HASHCODE = hashcode;}
return static_cast<T*>(cls);
}
This makes the map store a HashKey object with a dangling pointer. Also you are returning a reference to a member of a function local object called xx in FindClass. The use of this reference invokes undefined behaviour.
Consider renaming the map's key type. The hash code itself shouldn't be a key. And as your operator== for HashKey suggests, you don't want the actual key to be the hash code but the sequence of integers of variable length. Also, consider storing the sequence inside of the key type instead of a pointer, for example, as a vector. In addition, avoid returning references to function local objects.
Using unordered_map does not guarantee that you do not get has collisions, which is what you describe here.
there are more than one instance that
has the same parameters and HASHCODE
You can tune your hashing algorithm to minimize this, but in the (inevitable) collision case, the hash container extends the list of objects in the bucket corresponding to that hashcode. Equality comparison is then used to resolve the collision to a specific matching object. This may be where your problem lies - perhaps your operator== does not properly disambiguate similar but not identical objects.
You cannot expect one object per bucket, or the container would grow unbounded in large collection size cases.
btw if you are using a newer compiler you may find it supports std::unordered_map, so you can use that (the official STL version) instead of the Boost version.