I'm working on a c++ project and I have a case as below:
void func(int a, int b)
{
if (some_bool)
{
generateString(generateFunc()); // different
}
for (auto it : myVector)
{
// do something
for (int i = 0; i < a + b; ++i)
{
if (some_bool2)
{
myData = generateInt();
}
else
{
myData2 = generateInt2(); // different
}
}
}
}
void func(int a, int b, string str)
{
if (some_bool)
{
generateString(generateFunc(str)); // different
}
for (auto it : myVector)
{
// do something
for (int i = 0; i < a + b; ++i)
{
if (some_bool2)
{
myData = generateInt();
}
else
{
myData2 = convertStrToInt(str); //different
}
}
}
}
As you see, I have two overloading functions.
Their logical structures are the same but some details are not.
I'm considering if there is some technique which can merge them so that I can have a better design. Because for now I have to change two times if I need to do some change.
You can use templates and do something like this:
template<typename F, typename... A>
void func(int a, int b, F &&f, A&&... a)
{
if (some_bool)
{
generateString(generateFunc(std::forward<A>(a)...)); // different
}
for (auto it : myVector)
{
// do something
for (int i = 0; i < a + b; ++i)
{
if (some_bool2)
{
myData = generateInt();
}
else
{
myData2 = std::forward<F>(f)(std::forward<A>(a)...); //different
}
}
}
}
Then call your function as it follows:
func(0, 0, generateInt2);
// or
func(0, 0, convertStrToInt, std::string{0});
Related
I have a code that uses a while statement. Inside
the conditional expression I do a lookup. At the same time the conditional expression checks the return value:
#include <map>
struct a {
a *up;
std::map<int,int> tbl;
};
void p(a *_a, int id) {
decltype(_a->tbl)::iterator i;
while (_a && (i = _a->tbl.find(id)) != _a->tbl.end()) {
i->second += 1;
_a = _a->up;
}
}
int main(int arc, char **argv) {
a _a1{0,{{0,10},{1,10}}};
a _a0{&_a1,{{2,11},{3,11}}};
p(&_a0, 0);
return 0;
}
However I would like to get rid of the explicit declaration of i. I would like to use auto. In pseudocode:
...
void p(a *_a, int id) {
while (_a && ((auto i = _a->tbl.find(id))) != _a->tbl.end()) {
i->second += 1;
_a = _a->up;
}
}
...
Is there a construct in c++11/14/17 that supports this kind of declarations inside an expression? Not only while(auto i = 1) {...} style declarations? Maybe there are some new features that allow this?
How about separating the two conditions? The main one for the loop to continue is _a, and the secondary one (which may always be true) is _a->tbl.find(id) != _a->tbl.end(). Return on its negation:
void p(a *_a, int id) {
while (_a) {
auto i = _a->tbl.find(id);
if (i == _a->tbl.end()) {
return;
}
i->second += 1;
_a = _a->up;
}
}
Yesterday my friend challenged me to write a function in C which would return an array of function pointers where i-th function would return i.
It is easy to get a similar effect in C++, but I am not sure how to do it in C.
Can anyone help me with that?
Edit.
The effect that I am looking for is something equivalent to this.
vector <function<int()>> get_functions(int n) {
vector <function<int()>> functions;
for (int i = 0; i < n; ++i) {
functions.emplace_back([i]() {
return i;
});
}
return functions;
}
int main() {
auto functions = get_functions(10);
for (auto f:functions) {
cout << f() << endl;
}
return 0;
}
Edit.
As asked in the comment section I provide my poor attempt on the challenge.
typedef int (*fun_t)(void);
int fun() { return 0; }
int fun1() { return 1; }
fun_t *get_functions() {
fun_t *functions = malloc(sizeof(fun_t) * 2);
functions[0] = fun;
functions[1] = fun1;
return functions;
}
int main() {
fun_t* funs=get_functions();
for (int i = 0; i < 2; ++i) {
printf("%d\n",funs[i]());
}
free(funs);
}
The C++ code is cheating. function<int()> is not a function pointer; in fact, it's not a pointer at all, it's a class.
Therefore the equivalent C code would look something like this:
#include <stdio.h>
#include <stdlib.h>
// function<int ()>, simplified version just for this task
typedef struct {
int (*code)(int);
int ctx;
} function_int_t;
// function<int()>::operator()()
int call(function_int_t fun) {
return fun.code(fun.ctx);
}
// lambda body
int proto(int ctx) {
return ctx;
}
function_int_t *get_functions(size_t n) {
function_int_t *functions = calloc(n, sizeof *functions);
if (!functions) {
abort(); // hey, that's how C++ does it
}
for (size_t i = 0; i < n; i++) {
functions[i] = (function_int_t){ proto, i }; // capture i
}
return functions;
}
int main(void) {
size_t n = 10;
function_int_t *functions = get_functions(n);
for (size_t i = 0; i < n; i++) {
printf("%d\n", call(functions[i]));
}
free(functions);
return 0;
}
I am trying to add a Complex number, represented in Complex class to an array of complex.
#pragma once
class Complex
{
private:
int re, im;
public:
Complex() {};
Complex(int a, int b) { re = a; im = b; }
Complex(const Complex &);
Complex& operator=(const Complex &);
//operators overloading
bool operator==(Complex);
//member function
void print();
};
class Multime
{
private:
Complex *array;
static int nrElem;
int dim;
public:
Multime();
Multime(int a) { dim = a; nrElem = 0; array = new Complex[dim]; }
~Multime();
//Operators overloading
Multime& operator += (Complex b);
Multime& operator =(const Multime &);
//member function
void print();
};
Functions.cpp
#include <iostream>
#include "Multime.h"
using namespace std;
Complex::Complex(const Complex &a)
{
re = a.re;
im = a.im;
}
Complex& Complex::operator= (const Complex&a)
{
re = a.re;
im = a.im;
return *this;
}
void Complex::print()
{
cout << re << "+" << im << "i" << endl;
}
bool Complex::operator==(const Complex a)
{
return (re == a.re && im == a.im);
}
//Multime
//
Multime::Multime()
{
dim = 0;
nrElem = 0;
array = nullptr;
}
Multime::~Multime()
{
if (nullptr != array)
{
delete[] array;
}
}
void Multime::print()
{
for (int i = 0; i < nrElem; ++i)
{
array[i].print();
}
cout << endl;
}
Multime& Multime::operator +=(Complex a)
{
int g = 0;
if (nrElem < dim)
{
for (int i = 0; i < nrElem; ++i)
{
if (array[i] == a)
{
g = 1;
}
}
}
if (!g) //Element not found, can insert
{
array[nrElem++] = a;
}
return *this;
}
Multime& Multime::operator =(const Multime & a)
{
dim = a.dim;
array = new Complex[dim];
for (int i = 0; i < nrElem; ++i)
{
array[i] = a.array[i];
}
return *this;
}
In main I wrote the initialization for the static int Multime::nrElem = 0; after preprocessor directivesand and in main(void):
Multime a[50];
Complex f(2, 5), b(1, 3), c(5, 4);
a+=f;
but I get the error: binary '+=': no global operator found.I don't wanna use a friend function for +. I tried to create separate functions for + and = but the error is still there.
LE. The problem was in main a it's an array of Multime. Correct one, using initialization constructor: Multime a(50);
a+=f;
is not valid since a is an array of Multime, not an object of type Multime.
If you want to use the operator+= on one object, you could use
a[0] += f;
If you want to use it for all the objects in the array, use a loop.
for ( auto& item : a )
{
item += f;
}
guys! I am trying to do this:
int (*filterFunc)(Medicine* criteria, Medicine*);
DynamicVector<Medicine>* filter2(Medicine* criteria, filterFunc f); //error
but I get an error: 'filterFunc' is not a type
I am trying to do this because I want a general filter so then I can do this:
int filterPrice(Pet* pet) {
if (pet->price > 10 && pet->price < 100) {
return 0;
}
return 1;
}
VectorDinamic* filter2(Pet* criteria, filterFunc f) {
VectorDinamic* v = getAll(ctr->repo);
VectorDinamic* rez = creazaVectorDinamic();
int nrElems = getNrElemente(v);
int i;
for (i = 0; i < nrElems; i++) {
Pet* pet = get(v, i);
if (!f(criteria, pet)) {
add(rez, copyPet(pet));
}
}
return rez;
}
VectorDinamic* filterByPrice(float price) {
Pet* criteria = createPet(1, "", "", price);
VectorDinamic* rez = filter2(ctr, criteria, filterByPriceGr);
destroyPet(criteria);
return rez;
}
How can I solve this problem?
You forgot a typedef, to declare the type. Otherwise this declaration just creates a variable of type int(*)(Medicine*,Medicine*).
typedef int (*filterFunc)(Medicine* criteria, Medicine*);
//^^^^^^^
struct M{
T opIndex(uint i){ ... }
}
which gives me this:
m[i]
but what if I want it in two dimension so that I could do:
m[i][j]
is there anyway to do this?
Yes, you can do the C++ way of returning a temporary object (struct is best in D's case) which also has an index operator overload.
But a better idea in D is to go for the syntax m[i, j]:
struct S
{
uint opIndex(uint i, uint j)
{
return i + j;
}
}
void main()
{
S s;
assert(s[2, 3] == 5);
}
If you still want to use m[i][j], a nested struct gives you some syntactic leeway:
struct S
{
auto opIndex(uint i)
{
struct Temp
{
uint opIndex(uint j)
{
return i + j;
}
}
return Temp();
}
}
void main()
{
S s;
assert(s[2][3] == 5);
}