How to use remove_if with erase - c++

I would like to know how to remove an object from a list base on a condition.
After researching, this is what I got, but it still doesn't work!
So I would like to know how to use remove_if with erase.
Class A
{
public:
A(int x,int y);
int x;
int y;
};
int main()
{
list<A> listA;
A lista1(123,32);
listA.push_back(lista1);
A lista2(3123,1233);
listA.push_back(lista2);
A lista3(123,4123);
listA.push_back(lista3);
//HERE HOW TO REMOVE LIST if x = 123?
listA.erase(remove_if(listA.begin(),listA.end(),/*REMOVE CRITERIA*/);
}

std::list has a remove_if member function:
http://www.cplusplus.com/reference/stl/list/remove_if/
For your predicate you could either write a functor:
struct RemoveIfX
{
RemoveIfX(int x) : m_x(x) {}
bool operator() (const A& a)
{
return (a.x == m_x);
}
int m_x;
};
listA.remove_if(RemoveIfX(123));
Or use a lambda:
listA.remove_if([](const A& a) { return (a.x == 123); });

Related

How can I implement `my_class_instance(a, b) = value` operation

I have a class Flight and I need to implement two operations:
Flight s;
auto value = s(1, 2);
s(3, 4) = value;
I know how to implement first operation:
class Flight
{
public:
int operator()(int a, int b) {
return cache.for(a, b).get();
}
private:
// cache
}
But I don't know implement second operation. Something like this:
void operator()=(int a, int b, int value) {
cache.for(a, b).set(value);
}
Now I have an error operation is not accessible for expression like s(3, 4) = value;.
How can I implement this operation?
There is no ()= operator. It is two separate operators - operator(), and then operator= on the return value of operator().
Since you want to use separate get() and set() methods inside the cache, you will have to make your Flight::operator() return a helper proxy, and then you can implement proxy::operator int to call the get() method and proxy::operator= to call the set() method, eg:
class Flight
{
public:
class Proxy
{
private:
Flight &f;
int a, b;
public:
Proxy(Flight &f, int a, int b) : f(f), a(a), b(b) {}
operator int() {
return f.cache.For(a, b).get();
};
Proxy& operator=(int value) {
f.cache.For(a, b).set(value);
return *this;
}
};
friend class Proxy;
Proxy operator()(int a, int b) {
return Proxy{*this, a, b};
}
private:
// cache
};
Then your example will work as you want:
Flight s;
int value = s(1, 2); // <-- important - int, not auto!
s(3, 4) = value;
Live Demo

How to remove an element from a vector using remove_if

I have the below code: I face compilation error in remove function. I want to remove the elements from the vector whose elements have an x match the value of input x.
class A
{
int x,y;
public:
init(int a, int b)
{
x = a; y= b;
}
int getX(){return x;}
}
class B
{
public:
void add (int a, int b)
{
A a1;
a1.init(a,b);
MyVector.push_back(a1);
}
void remove(int x)
{
MyVector.erase(remove_if(MyVector.begin(), MyVector.end(),
[&vec](int x){return (vec.getX() == x);}), MyVector.end());
}
vector<A> MyVector;
}
You must give a return type to init(int a, int b) and you've missed two ;s after the classes definitions and used std::remove_if() incorrectly. here is its documentation
#include <vector>
#include <algorithm>
class A
{
int x,y;
public:
void init(int a, int b)
{
x = a; y= b;
}
int getX(){return x;}
};
class B
{
public:
void add (int a, int b)
{
A a1;
a1.init(a,b);
MyVector.push_back(a1);
}
void remove(int x)
{
MyVector.erase(std::remove_if(MyVector.begin(), MyVector.end(),
[&x](auto & el){return (el.getX() == x);}), MyVector.end());
}
std::vector<A> MyVector;
};
Note that auto & el == A & el. std::remove_if iterates over the vector and passes its elements to the lambda, hence the lambda argument type should be as the vector's one.

How to validate input parameters in C++ constructor?

Following example shows the crux of the problem. I need to initialize const members of a class. This can only be done in the initializer-list and not in constructor body. I want to assert or throw an error if input to the constructor is invalid, that is, if the vector size is less than 3.
class A {
// In following constructor, how do we make sure if params.size()
// is at least 3.
A(const std::vector<int>& params):
x(params[0]), y(params[1]), z(params[2]) {}
private:
const int x;
const int y;
const int z;
};
Please advise how to achieve this in Modern C++ (11 and later)
Just add a layer of abstraction. You can write a function that makes sure the vector is of the correct size and you can even make sure the values are in an expected range, if you have one. That would look like
class A {
A(const std::vector<int>& params):
x(verify(params, 0)), y(verify(params, 1)), z(verify(params, 3)) {}
private:
static int verify(const std::vector<int>& params, int index)
{
if (params.size() < 4) // or use if (params.size() <= index) if you only care if the index will work
throw something;
return params[index];
}
const int x;
const int y;
const int z;
};
const members can only be initialized in the constructors's member initialization list. To validate the caller's input, you would have to call a helper function to validate each input value before passing it to the corresponding member, eg:
int check(const std::vector<int> &params, int index) {
if (params.size() <= index) throw std::length_error("");
return params[index];
}
class A {
A(const std::vector<int>& params):
x(check(params, 0)), y(check(params, 1)), z(check(params, 3)) {}
private:
const int x;
const int y;
const int z;
};
Or, simply utilize the vector's own built-in bounds checking instead:
class A {
A(const std::vector<int>& params):
x(params.at(0)), y(params.at(1)), z(params.at(3)) {}
private:
const int x;
const int y;
const int z;
};
Not as elegant as other solutions but... you can simply add a throw in a ternary operator inside the initialization of the first constant
class A
{
private:
const int x;
const int y;
const int z;
public:
A (const std::vector<int>& params)
: x{ params.size() < 4u ? throw std::runtime_error{"!"}
: params[0] },
y{params[1]}, z{params[3]}
{ }
};
Off Topic suggestion: if A is a class, maybe it's better that the constructor is public.
Other option extra layer through conversion:
class A_params{
friend class A;
int x;
int y;
int z;
void validate();
public:
A_params(std::initializer_list<int>);
A_params(const std::vector<int>&);
A_params(int(&)[3]);
//...
};
class A {
// In following constructor, how do we make sure if params.size()
// is at least 3.
public:
A(A_params params):
x(params.x), y(params.y), z(params.z) {}
private:
const int x;
const int y;
const int z;
};

Ways to represent pattern in various languages

I have some C++ code. I'm duplicating a pattern repeatedly in it which isn't pleasant.
class layerclass {
public:
vector<int> a;
vector<int> b;
vector<int> c;
bool isInA(int x) { return a.find(x) != a.end(); } // true if x is in a
bool isInB ...
bool isInC ...
};
class innerlayer : public layerclass {
public:
layerclass *outerlayer;
bool isInA(int x) {
if (layerclass::isInA(x)) return true;
return outerlayer->isInA(x);
}
bool isInB(int x) ... // these two fn's will be identical to isInA()
bool isInC(int x) ... // with the exception of calling isInB/C()
};
In my case there really are only about 3 containers to search this way, but it's very bothersome for me to see. A solution might be to tag-dispatch somehow:
class layerclass {
public:
vector<int> a;
vector<int> b;
vector<int> c;
enum class members { a, b, c };
bool isIn(int x, members m) {
switch (m) {
case members::a: return a.find(x) != a.end();
...
}
};
class innerlayer : public layerclass {
public:
layerclass *outerlayer;
bool isIn(int x, member m) {
if (layerclass::isIn(x, m) return true;
return outerlayer->isIn(x, m);
}
};
Ok that's a little better but I still have the duplicated code in layerclass::isIn() and have to maintain the enum. Is this the best I cand do in C++? Do other languages offer a convenient solution to this outside of something like a preprocessor macro?
You can rewrite the class as follows, so there is no duplicate code in isIn
class layerclass {
public:
vector<int> a;
vector<int> b;
vector<int> c;
bool isIn(vector<int> &vec, int x) { return vec.find(x) != a.end(); }
bool isInA(int x) { return isIn(a, x); }
bool isInB(int x) { return isIn(b, x); }
bool isInC(int x) { return isIn(c, x); }
};

Unified wrapper around const and non-const pointers

I am using GNU Scientific Library in my C++ project. For convience, I would like to trasparently wrap gsl_vector* in a C++ class (to add a bunch of domain specific functions and to simplify interface). But I am getting perplexed with how to deal with const gsl_vector*. Let me explain. Let me start with this minimalistic wrapper.
class Vector {
gsl_vector* vector_;
public:
Vector(gsl_vector* vector): vector_(vector) {}
double& operator()(int i) {
return *gsl_vector_ptr(vector_, i);
}
};
Suppose, further, that I have two functions. One is defined as follows:
int f(Vector& x) {
\\ do some math, e.g. x(0) = 0.0;
return 0;
}
Another one is a callback function that has to use GSL types, and is defined as follows:
int gsl_f(gsl_vector* x) {
Vector xx(x);
return f(xx);
}
This works fine. Now, suppose the callback has a constant signature:
int gsl_f(const gsl_vector* x);
Then I can redefine my Vector class and my f function accordingly:
class Vector {
const gsl_vector* vector_;
public:
Vector(const gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_const_ptr(vector_, i);
}
};
int f(const Vector& x) {
\\ do some math
return 0;
}
Also works. Now, I want my wrapper class to suit both situations. For example, I want to be able to do the following, preserving the safety of const:
int f(const Vector& x, Vector& y) {
\\ do some math
return 0;
}
int gsl_f(const gsl_vector* x, gsl_vector* y) {
Vector yy(y);
return f(x, yy);
}
I can do it by having a Vector with two pointers, const and non-const, and remembering whether it was initialized from a const or non-const member. My question is, can I do it without runtime checks? After all, all the information is there at the compile time.
Proposal (not wonderful, but should work):
class Vector {
gsl_vector* vector_;
const gsl_vector* const_vector_;
public:
Vector(const gsl_vector* vector): vector_(nullptr), const_vector_(vector) {}
Vector(gsl_vector* vector): vector_(vector), const_vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(const_vector_, i);
}
double& operator () (int i) {
return *gsl_vector_ptr(vector_, i);
}
};
Second possibility:
class Vector {
private:
gsl_vector* vector_;
Vector(gsl_vector* vector): vector_(vector) {}
public:
static const Vector* Create (const gsl_vector* vector) {
return new Vector (const_cast<Vector *> vector);
}
static Vector* Create (gsl_vector* vector) {
return new Vector (vector);
}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
double& operator () (int i) {
return *gsl_vector_ptr(vector_, i);
}
};
Combining both classes should work as expected, have you tried it?
class Vector {
gsl_vector* vector_;
public:
Vector(gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
double& operator()(int i) {
return *gsl_vector_ptr(vector_, i);
}
operator const_Vector()
{
return const_Vector(vector_);
}
};
class const_Vector {
const gsl_vector* vector_;
public:
const_Vector(const gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
};
Function signature needs to look this way:
int f(const_Vector& x, Vector& y) {
\\ do some math
return 0;
}
This followes a similar scheme like the iterator and const_iterator.
Maybe you have a situation which this will not work,. you should post this situation and we can try to solve it.
You can also use some kind of inheritance with pointer to data. further - templates can be used to create overloaded function returning either one or second version depending on input pointer types.
class JSONChannelFullConfigConst:
public JSONObjectRenderer {
public:
JSONChannelFullConfigConst(const uint8_t * channel_id,
const sensors_single_channel_config_t * cfg) :
j_channel_id(channel_id),
j_cfg(cfg) {
}
private:
const uint8_t * const j_channel_id;
const sensors_single_channel_config_t * const j_cfg;
void renderFields(rlf::UcOstreamBase& os) const;
public:
uint8_t getId() const {
return *j_channel_id;
}
};
class JSONChannelFullConfig:
public JSONChannelFullConfigConst,
public JSONObjectParser {
public:
JSONChannelFullConfig(uint8_t * channel_id, sensors_single_channel_config_t * cfg) :
JSONChannelFullConfigConst(channel_id, cfg),
j_channel_id(channel_id),
j_cfg(cfg) {
}
void setId(uint8_t id) {
*j_channel_id = id;
}
private:
uint8_t * const j_channel_id;
sensors_single_channel_config_t * const j_cfg;
virtual bool parseNameValuePair(const char * name, rlf::UcIstream & value);
};