stable_sort in C++ - c++

Im trying to use stable_sort in order to sort a vector of pointers
to a certain class. I've a code like this :
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class B
{
public :
B(int y, int j) {x = y, r = j;};
void getVal() {cout << x << endl; };
int x;
int r;
};
bool compareB(B* b1, B* b2)
{
return b1->getVal() < b2->getVal();
}
int main()
{
B b1(3, 4), b2(-5, 7), b3(12, 111);
vector<B*> myVec;
myVec.push_back(&b1);
myVec.push_back(&b2);
myVec.push_back(&b3);
std::stable_sort(myVec.begin(), myVec.end(), compareB);
for (size_t size = 0; size < myVec.size(); ++size)
{
myVec[size]->getVal();
}
return 0;
}
However, I get the foolowing error while compiling it :
"error: invalid operands of types 'void' and 'void' to binary 'operator<'
return b1->getVal() < b2->getVal();"
Can someone help me ?

The problem is with
void getVal() {cout << x << endl; };
It returns void instead of some value.
When you use it in return b1->getVal() < b2->getVal(); it boils down to return void < void; which will not compile.
You should be able to change it to
int getVal() { return x; };

Related

C++ operator overloading [] and return types

I'm just revisiting C++, and I have a question about overloading of the [] operator, and more specifically why my program doesn't work.
Given the following code in vec.cpp:
double Vec::operator[](unsigned int i) const {
return this->values[i];
}
double & Vec::operator[](unsigned int i) {
return this->values[i];
}
These are defined in vec.h as methods to the Vec class, and if I do not use the operator in my main.cpp, all is fine and dandy. It compiles just as normal with no errors.
However once I do this in my main function (which is using std::cout and std::endl):
cout << a[0] << endl;
Things go wrong. The errors I get are a bunch of
candidate function template not viable: no known conversion from 'Vec' to 'char' for 2nd argument
operator<<(basic_ostream<_CharT, _Traits>& __os, char __cn)
where you can replace 'char' with any primitive data type.
Here is a working example
// In vec.h
#pragma once
#include <string>
#include <iostream>
class Vec {
private:
int dims;
double *values;
public:
Vec(int dims, double values[]);
double operator [](unsigned int i) const;
double& operator[](unsigned int i);
};
// In vec.cpp
#include <iostream>
#include <string>
#include <cmath>
#include "vec.h"
using std::cerr, std::endl, std::cout;
Vec::Vec(int dims, double values[]) {
this->dims = dims;
this->values = new double[dims];
for(int i = 0; i < dims; i++) {
this->values[i] = values[i];
}
}
double Vec::operator[](unsigned int i) const {
if(i >= this->dims) {
cerr << "Elem out of range" << endl;
}
return this->values[i];
}
double & Vec::operator[](unsigned int i) {
if(i >= this->dims) {
cerr << "Elem out of range" << endl;
}
return this->values[i];
}
// In main.cpp
#include <iostream>
#include <string>
#include "vec.h"
using std::cout, std::endl;
int main() {
double avals[2];
avals[0] = 1.0;
avals[1] = 2.0;
Vec *a = new Vec(2, avals);
cout << a[0] << endl; // Error occurs here
return 0;
}
Can anyone help me sort this out?
In this declaration
Vec *a = new Vec(2, avals);
there is declared a pointer of the type Vec *. So an expression with the dereferenced pointer has the type Vec.
So in this statement
cout << a[0] << endl;
the expression a[0] has the type Vec.
It seems you mean
( *a )[0]
or
a[0][0]

Return pointer to array virtual template function

I would like to return an array to a pointer, in a virtual function that is a member of a derived class of a template class. In details, my classes definition is:
Sampler.h
#ifndef SAMPLER_H
#define SAMPLER_H
template <class T>
class Sampler
{
public:
virtual T getnumber()=0;
virtual T* simulation(int n)=0;
};
class UniformSampler:public Sampler<double>
{
public:
virtual double getnumber();
virtual double* simulation(int n);
UniformSampler(double a=0.0, double b=1.0);
private:
double low_bound;
double up_bound;
};
#endif
The class Sampler is a template class in order to be able to derive an other sampler with vectors later. The implementation is:
Sampler.cpp
#include "Sampler.h"
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
//Uniform
UniformSampler::UniformSampler(double a, double b)
{
low_bound=a;
up_bound=b;
}
double UniformSampler::getnumber()
{
int myrand=rand();
while((myrand==0)||(myrand==RAND_MAX)){myrand = rand(); } //We want a number in (0, RAND_MAX).
double myuni = myrand/static_cast<double>(RAND_MAX); //Create a number in (0,1).
return low_bound + myuni*(up_bound-low_bound);
}
double* UniformSampler::simulation(int n){
double simulations[n];
for(int i=0; i<n; i++){
simulations[i] = this->getnumber();
}
return simulations;
}
My problem is that, when I try to call this program in the main(), it looks like the assignment of the pointer doesn't work. Here is my main.cpp:
#include <iostream>
#include <math.h>
#include <cstdlib>
#include <time.h>
using namespace std;
#include "Sampler.h"
int main(){
srand(time(0));
int n=10;
double *unif = new double[n];
UniformSampler uni;
unif = uni.simulation(n);
for ( int i = 0; i < n; i++ ) {
cout << "*(p + " << i << ") : ";
cout << *(unif + i) << endl;
}
delete[] unif;
return 0;
}
When I run it, it doesn't print any of the elements that unif points to. I don't understand what is wrong there.
UniformSampler::simulation is twice wrong:
double simulations[n]; uses VLA extension, so not C++ standard compliant.
you return pointer on local variable, so dangling pointer.
Solution: use std::vector instead.
#include <vector>
template <class T>
class Sampler
{
public:
virtual ~Sampler() = default;
virtual T getnumber() = 0;
virtual std::vector<T> simulation(int n) = 0;
};
class UniformSampler:public Sampler<double>
{
public:
explicit UniformSampler(double a=0.0, double b=1.0);
double getnumber() overrid;
std::vector<double> simulation(int n) override
{
std::vector<double> res(n);
for (auto& val : res){
res = getnumber();
}
return res;
}
private:
double low_bound;
double up_bound;
};
int main(){
srand(time(0));
constexpr int n = 10;
UniformSampler uni;
auto unif = uni.simulation(n);
for (int i = 0; i < n; i++ ) {
std::cout << "p[" << i << "]: " << unif[i] << endl;
}
}

Call Boost::odeint stepper.do_step() function inside class

What I am trying to do in this question is in line with what I was trying to do in: Dynamic Eigen vectors in Boost::odeint. However now I am trying to encapsulate it all in a class as follows:
#include <iostream>
#include <Eigen/Core>
#include <cstdlib>
#include <boost/numeric/odeint.hpp>
#include <boost/numeric/odeint/external/eigen/eigen_algebra.hpp>
namespace odeint = boost::numeric::odeint;
typedef odeint::runge_kutta_dopri5<Eigen::VectorXd, double, Eigen::VectorXd, double, odeint::vector_space_algebra> stepper;
class foo
{
private:
Eigen::VectorXd m_x;
Eigen::MatrixXd m_A;
double m_t, m_dt;
public:
foo(int nr_of_states){ //ctor
m_t = 0;
m_dt = 1.0;
m_x = Eigen::VectorXd(nr_of_states);
m_A = Eigen::MatrixXd(nr_of_states, nr_of_states);
srand(365);
for (int i = 0; i < m_A.size(); i++){
*(m_A.data()+i) = ((double)rand()/(double)RAND_MAX);}
for (int i = 0; i < m_x.size(); i++){
*(m_x.data()+i) = i;}
}
void ODE_function(const Eigen::VectorXd &x, Eigen::VectorXd &dxdt, double){
dxdt = m_A * x;}
void next_step(){
odeint::integrate_adaptive(stepper(), ODE_function, m_x, m_t, (m_t+(1*m_dt)), m_dt);}
Eigen::VectorXd get_states(){
return m_x;}
};
int main()
{
int nr_of_states;
std::cout << "How many (random) states would you like to simulate?: ";
std::cin >> nr_of_states;
std::cout << std::endl;
foo f1(nr_of_states);
for (int i = 0; i < 100; i++){
f1.next_step();}
std::cout <<std::endl << "final state vector: " << std::endl << f1.get_states() << std::endl;
return 0;
}
I am using the MinGW 64 bit compiler to compile above code when I get the following error message:
\boost\boost_1_59_0\boost\numeric\odeint\stepper\base\explicit_error_stepper_fsal_base.hpp|297|error:
must use '.' or '->' to call pointer-to-member function in 'sys
(...)', e.g. '(... ->* sys) (...)'|
Is what I am trying to do here in principle possible? If yes, how should above code be adapted?

How do I pass a list of values to a function expecting an array?

In my program I want to pass a few variables into a function and have that function run a for loop to write the data to console.
This is my code:
void WriteValue(int[] arr)
{
for(auto c : arr)
std::cout<<arr<<std::endl;
}
int main()
{
int a = 0;
int b = 1;
int c = 3;
WriteValue(a,b,c);
return 0;
}
I know this would work in C# with params, but I don't have that option. How do I get this to run in C++?
Here's a very simple and flexible way:
#include <iostream>
template<typename T>
void WriteValue(const T& arr)
{
for(auto c : arr)
std::cout << c << std::endl;
}
int main()
{
int a = 0;
int b = 1;
int c = 3;
WriteValue(std::array<int, 3>{a,b,c});
// nicer C99 way: WriteValue((int[]){a,b,c});
return 0;
}
If you only want to be able to pass a list of ints (and it has to be a brace-separated list, not an existing array), you can instead do
#include <iostream>
#include <initializer_list>
void WriteValue(const std::initializer_list<int>& arr)
{
for(auto c : arr)
std::cout << c << std::endl;
}
int main()
{
int a = 0;
int b = 1;
int c = 3;
WriteValue({a,b,c});
return 0;
}
Unfortunately, VS2012 doesn't support this. You can upgrade to Visual 2013 (the Express Edition and Community Edition are both free), or you can use a helper variable:
#include <iostream>
template<typename T>
void WriteValue(const T& arr)
{
for(auto c : arr)
std::cout << c << std::endl;
}
int main()
{
int a = 0;
int b = 1;
int c = 3;
int args[] = { a, b, c };
WriteValue(args);
return 0;
}

How can I pass an array of objects?

Here I have a very simple program. My aim is to let b equal c, that is to copy all the content of c into b. But I don't know how. The getdata() function returns a pointer pointing to array of objects c, but how can it be used to put c into b?
#include<iostream>
#include<stdlib.h>
using namespace std;
class A
{
public:
A(int i,int j):length(i),high(j){}
int length,high;
};
class B
{
private:
A c[3] = {A(9,9),A(9,9),A(9,9)};
public:
A* getdata()
{
return c;
}
};
int main()
{
A b[3]={A(0,0),A(0,0),A(0,0)};
B *x = new B();
cout<< x->getdata() <<endl;
cout << b[1].length<<endl;
return 0;
}
In modern C++, make yourself a favor and use a convenient container class to store your arrays, like STL std::vector (instead of using raw C-like arrays).
Among other features, std::vector defines an overload of operator=(), which makes it possible to copy a source vector to a destination vector using a simple b=c; syntax.
#include <vector> // for STL vector
....
std::vector<A> v; // define a vector of A's
// use vector::push_back() method or .emplace_back()
// or brace init syntax to add content in vector...
std::vector<A> w = v; // duplicate v's content in w
That's a possible partial modification of your code, using std::vector (live here on codepad):
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A(int l, int h) : length(l), high(h) {}
int length, high;
};
class B
{
private:
vector<A> c;
public:
const vector<A>& getData() const
{
return c;
}
void setData(const vector<A>& sourceData)
{
c = sourceData;
}
};
int main()
{
vector<A> data;
for (int i = 0; i < 3; ++i) // fill with some test data...
data.push_back(A(i,i));
B b;
b.setData(data);
const vector<A>& x = b.getData();
for (size_t i = 0; i < x.size(); ++i) // feel free to use range-for with C++11 compilers
cout << "A(" << x[i].length << ", " << x[i].high << ")\n";
}
Instead of creating an array of A i.e. 'b' in main, create a pointer to A. And then initialize it by calling the getdata().
A *b;
B *x = new B();
b = x->getdata();
Here is an example
#include <iostream>
#include <algorithm>
class A
{
public:
A( int i, int j ) : length( i ), high( j ){}
int length, high;
};
class B
{
private:
A c[3] = {A(9,9),A(9,9),A(9,9)};
public:
A* getdata()
{
return c;
}
};
int main()
{
A b[3] = { A(0,0), A(0,0), A(0,0) };
B *x = new B();
A *c = x->getdata();
std::copy( c, c + 3, b );
for ( const A &a : b ) std::cout << a.length << '\t' << a.high << std::endl;
delete []x;
return 0;
}
The output is
9 9
9 9
9 9
Instead of standard algorithm std::copy you may use an ordinary loop. For example
for ( size_t i = 0; i < 3; i++ ) b[i] = c[i];