Basically I need to transform a ternary operator into a conditional operator using "if...else" cycle.
function getBestStudent (students) {
const bestAverageMark = students.reduce((a, b) => getAverageMark(a) > getAverageMark(b) ? a : b)
return bestAverageMark
}
"getAverageMark" here is another function.
How can I transform this into a conditional operator "if... else"? Thank you!
you might wanna check out the mdn docs on arrow function expressions
function getBestStudent (students) {
const bestAverageMark = students.reduce((a, b) => {
if (getAverageMark(a) > getAverageMark(b)) {
return a;
} else {
return b;
}
});
return bestAverageMark;
}
this could be simplified to
function getBestAverageMark (a,b) {
if (getAverageMark(a) > getAverageMark(b)) {
return a;
} else {
return b;
}
}
function getBestStudent (students) {
return students.reduce(getBestAverageMark);
}
Related
I am trying to code a formula from propositional logic in a c++ class.
A formula can be:
A variable
A negation of a formula
Two formulas joined by a connective
I could not fined a way to define these three different structures into one class so I decided to declare them as different subclasses. The problem I am having is when declaring the opperators they do not seem to override the standard ones correctly. && is returning a bool instead of a shared_ptr
Solved: just used a shared_ptr in the baseclass to itself to avoid any slicing.
#include <iostream>
#include <memory>
using namespace std;
// {0, 1, 2}
// {and, or, implies}
class formula
{
shared_ptr <formula> F;
public:
formula ()
{}
formula (shared_ptr <formula> f)
{
F = f;
}
formula (formula* f)
{
F = shared_ptr <formula> (f);
}
virtual bool evaluate ()
{
return F -> evaluate ();
}
virtual string type ()
{
return F -> type ();
}
shared_ptr <formula> address ()
{
return F;
}
virtual void assign (bool b)
{
F -> assign (b);
}
formula operator&& (formula f);
formula operator|| (formula f);
formula operator>> (formula f);
formula operator! ();
};
class variable : public formula
{
bool value;
public:
void assign (bool b)
{
value = b;
}
bool evaluate ()
{
return value;
}
string type ()
{
return "variable";
}
};
class negation : public formula
{
shared_ptr <formula> arg;
public:
negation (formula f)
{
arg = f.address ();
}
bool evaluate ()
{
return !(arg -> evaluate ());
}
string type ()
{
return "negation";
}
};
class connected : public formula
{
shared_ptr <formula> lhs, rhs;
int C;
public:
connected (formula f, formula g, int c)
{
lhs = f.address ();
rhs = g.address ();
C = c;
}
bool evaluate ()
{
if (C == 0)
return lhs -> evaluate () && rhs -> evaluate ();
else if (C == 1)
return lhs -> evaluate () || rhs -> evaluate ();
else
return !(lhs -> evaluate ()) || rhs -> evaluate ();
}
string type ()
{
return "connected";
}
};
formula formula::operator&& (formula g)
{
shared_ptr <formula> temp (new connected (*this, g, 0));
formula f (temp);
return f;
}
formula formula::operator|| (formula g)
{
shared_ptr <formula> temp (new connected (*this, g, 1));
formula f (temp);
return f;
}
formula formula::operator>> (formula g)
{
shared_ptr <formula> temp (new connected (*this, g, 2));
formula f (temp);
return f;
}
formula formula::operator! ()
{
shared_ptr <formula> temp (new negation (*this));
formula f (temp);
return f;
}
int main ()
{
formula A (new variable), B (new variable);
A.assign(true);
B.assign(false);
formula x = A&&B, y = A||B, z = A>>B, w = !B;
cout << boolalpha;
cout << x.evaluate () << endl;
cout << y.evaluate () << endl;
cout << z.evaluate () << endl;
cout << w.evaluate () << endl << endl;
B.assign(true);
cout << boolalpha;
cout << x.evaluate () << endl;
cout << y.evaluate () << endl;
cout << z.evaluate () << endl;
cout << w.evaluate () << endl;
}
You define && to accept arguments of types formula and shared_ptr<formula>. This is weirdly asymmetric and will confuse you to no end. Then you are trying to apply it to two shared_ptr<formula>s. It is not going to work.
As a stopgap measure, change
cerr << (A&&B) -> type () << endl;
to
cerr << (*A && B) -> type () << endl;
However this is unsustainable in the long run.
I would recommend split formula in two classes, formula and formula_impl, where formula_impl contains all the virtual functions of the former formula and formula contains a shared_ptr<formula_impl>. formula implements what it can (operator&& and in the future maybe other things, like operator! and operator|| and whatnot) and delegates evaluate etc. to the formula_impl pointed to by the shared pointers. The end user only sees formula, never formula_impl.
formula should also define static functions that return a variable, a negation, and a conjunction.
Some additional notes.
assign is not a very good choice for a virtual function. You can only assign a variable. It makes no sense for other types of formulas. I would get rid of this function entirely, and pass the value to the constructor of variable instead.
Base class implementations should not print "error", or do anything else. They should be pure virtual functions instead.
Magic numbers (0 is conjunction, 1 is disjunction) are not a good idea. Define a enum. Treat the default case as an error.
#include <iostream>
using namespace std;
class Expression
{
private :
double val;
public :
Expression() : val(0)
{
}
Expression(double v) : val(v)
{
}
Expression operator +(Expression a)
{
Expression a1;
a1.val = val + a.val;
return a1;
}
Expression operator --()
{
Expression temp1;
temp1.val = --val;
return temp1;
}
Expression operator --(int)
{
return Expression(val--);
}
Expression operator * (Expression b1)
{
Expression b;
b.val = val * b1.val;
return b;
}
double showvalue()
{
return val;
}
};
int main()
{
Expression E1;
Expression E2(5.5) , E3;
E3(2.0);
cout << E3.showvalue();
cout << endl;
Expression E4;
E4 = E3;
E1 = E2+--E3*E4--;
cout << E1.showvalue();
return 0;
}
In the main where I have E3(2.0)
How would I overload so it would work without doing, Expression E3(2.0);
just E3(2.0);
Our teacher says there is a way to do this, so I want to know it
Again
I want it to be only E3(2.0) or any value inside, so it works
(filling so I can post
don't read this just adding details for no reason beacasue it says so)
You might have operator() acting as assigment.
class Expression
{
public:
Expression& operator=(double d) { val = d; return *this; }
void operator()(double d) { *this = d; }
// ...
};
This question already has an answer here:
Is there a way to do constructor delegation using a conditional in C++11?
(1 answer)
Closed 4 years ago.
The typical way (and the only one widely used) to delegate some part of the object initialization to another constructor is to call it using the initializer list, like so:
class Window
{
Window(int a);
Window(int a, void *b);
Window(string a);
Window(double a, double b) : Window((int) (a + b))
{
}
};
But sometimes there is a necessity to do some prep work or branch constructor calls.
Is this how it should be done?
class Window
{
Window(int a);
Window(int a, void *b);
Window(string a);
Window(double a, double b)
{
if (a * b == 0.0)
{
Window("ZERO");
}
else if (a * b > 100.0)
{
Window((int) (a + b), x);
}
else
{
Window((int) (a + b));
}
}
};
I have never seen anything like this; this is just my guess of how it could look (which appears to be working).
Are there any side effects or any undefined behavior to calling other constructors from the constructor body (and not from the initializer list)?
#Edit: I'm including the code I'm having a problem with below. Basically, I have an object that is a container for some data, and I store it in a std::map<CString, ValueContainer>. I employ a copy constructor, and an overloaded assignment operator. The insertion works fine when I add an instance to the map using the [] operator, but it doesn't when I use the insert_or_assign method, because it uses the copy constructor (which uses the branching that is the problem here). Here's a simplification of the class.
class ValueContainer
{
ValueContainer(const VOID *p_data, ULONG p_size)
{
if (p_data != NULL)
{
if (p_size > 0)
{
if (p_size <= sizeof(shortData))
{
memcpy(shortData, p_data, p_size);
}
else
{
longData = new BYTE[p_size];
memcpy(longData, p_data, p_size);
}
}
hasValue = TRUE;
size = p_size;
}
else
{
hasValue = FALSE;
size = 0;
}
}
ValueContainer(const ValueContainer &p_value)
{
if (p_value.HasValue())
{
if (p_value.size <= sizeof(shortData))
{
ValueContainer(p_value.shortData, p_value.size);
}
else
{
ValueContainer(p_value.longData, p_value.size);
}
}
else
{
ValueContainer();
}
}
ValueContainer(VOID) : ValueContainer(NULL, 0)
{
}
ValueContainer &operator =(const ValueContainer &p_value);
{
if (p_value.hasValue)
{
if (p_value.size <= sizeof(shortData))
{
if (longData != NULL)
{
free(longData);
longData = NULL;
}
memcpy(shortData, p_value.shortData, p_value.size);
}
else
{
if (p_value.size > size)
{
longData = (BYTE *) realloc(longData, p_value.size);
}
memcpy(longData, p_value.longData, p_value.size);
}
hasValue = TRUE;
size = p_value.size;
}
else
{
if (longData != NULL)
{
free(longData);
longData = NULL;
}
hasValue = FALSE;
size = 0;
}
return *this;
}
private:
BYTE shortData[16];
BYTE *longData = NULL;
BOOL hasValue;
ULONG size;
}
For your first example, this might be the way it can be done:
class Window
{
private:
void constructor_method(int a);
void constructor_method(int a, void *b);
void constructor_method(string a);
public:
Window(int a) {
constructor_method(a);
}
Window(int a, void *b) {
constructor_method(a, b);
}
Window(string a) {
constructor_method(a);
}
Window(double a, double b)
{
if (a * b == 0.0)
{
constructor_method("ZERO");
}
else if (a * b > 100.0)
{
constructor_method((int) (a + b), x);
}
else
{
constructor_method((int) (a + b));
}
}
};
I think the short answer to this question is "simplify your code." But if that's not an option, I think the next best alternative is a factory method:
class Window
{
private:
Window(int a);
Window(int a, void *b);
Window(string a);
public:
static Window Create(double a, double b)
{
if (a * b == 0.0)
{
return Window("ZERO");
}
else if (a * b > 100.0)
{
return Window((int) (a + b), x);
}
else
{
return Window((int) (a + b));
}
}
};
i have a big problem.. I wonna select the Storage Service via a wrapper class. The returning value must be an object within the storage service class. I pasted my current approach. But my mindset didn't worked so far.
Error:
error: inconsistent deduction for auto return type: ‘SQL*’ and then ‘REDIS*’ return new REDIS();
The big wish is to have an interface class which defines the struct and some "driver classes" which contains all necessary operations for the target storage service.
I hope you have another approach, how I can solve this problem..
#include <iostream>
class StorageTemplate {
public:
virtual bool UserhasSurName() = 0;
virtual bool UserhasGivenName() = 0;
};
class SQL: public StorageTemplate {
public:
bool UserhasSurName() {
//A SQL QUERY
return true;
}
bool UserhasGivenName() {
//AN ANOTHER SQL QUERY
return true;
}
};
class REDIS: public StorageTemplate {
public:
bool UserhasSurName() {
//A REDIS CALL
return false;
}
bool UserhasGivenName() {
//A REDIS CALL
return false;
}
};
class controller {
public:
auto test(int select) {
if( select == 1)
{
return new SQL();
} else {
return new REDIS();
}
}
};
int main(int argc, char const *argv[])
{
controller cont;
auto schnitzel = cont.test(1);
auto mitzel = cont.test(2);
std::cout << schnitzel->UserhasSurName() << std::endl;
std::cout << mitzel->UserhasSurName() << std::endl;
}
The problem you are facing is the following: Consider your function
auto test(int select) {
if (select == 1) {
return new SQL();
} else {
return new REDIS();
}
}
If you trying to evaluate test(1) this expands to
auto test(int select) {
if (true) {
return new SQL();
} else {
return new REDIS();
}
}
which results in a type error!
I show you three workarounds for your problem:
1. Function template and if constexpr
Make test a function template and check for the correct type using the C++17 feature if constexpr:
template<typename T>
auto test() {
if constexpr(std::is_same<T, SQL>::value) {
return new SQL();
} else {
return new REDIS();
}
}
Use it in main() like this:
int main(){
controller cont;
auto schnitzel = cont.test<SQL>();
auto mitzel = cont.test<REDIS>();
std::cout << schnitzel->UserhasSurName() << std::endl;
std::cout << mitzel->UserhasSurName() << std::endl;
}
2. Function template and std::unique_ptr
If you want to avoid using the if constexpr you can simply return an instance of std::unique_ptr instead of a raw pointer. This is the preferred way to do:
template<typename T>
auto test() {
return std::unique_ptr<T>(new T);
}
Alternatively you can just return std::make_unique<T>().
3. Returning an instance of the base class
This is is most obvious solution to avoid the type error: Just return an instance of the base class. As above a solution using smart pointers is preferred here:
std::unique_ptr<StorageTemplate> test(const int select) {
if (select == 1) {
return std::make_unique<SQL>();
} else {
return std::make_unique<REDIS>();
}
}
If you really want to avoid using smart pointers just use raw ones like this:
StorageTemplate* test(const int select) {
if (select == 1) {
return new SQL();
} else {
return new REDIS();
}
}
in this code
auto test(int select) {
if( select == 1)
{
return new SQL();
} else {
return new REDIS();
}
auto can't be deduced because it only match to exact type. so even if SQL and REDIS inherite from StorageTemplate, StorageTemplate won't be deduced. you need to spécifie the type
StorageTemplate* test(int select) {
if( select == 1)
{
return new SQL();
} else {
return new REDIS();
}
Error return Auto in test(),it's return two different types. Change by StorageTemplate*
class controller {
public:
StorageTemplate* test(int select) {
if( select == 1)
{
return new SQL();
} else {
return new REDIS();
}
}
};
I need help with a problem pertaining to classes. I know how to solve it but I am wondering if there is a better solution than my current idea.
Each Class Tile Object and Class Player Object has an x and y position. I would like to know if there is a way to expedite things. My current idea is if-else statements like this:
if(x==1) {
if(y==1) {
return tileone1;
} else if(y==2) {
return tileone2;
} else if(y==3) {
return tileone3;
} else if(y==4) {
return tileone4;
} else if(y==5) {
return tileone5;
} //......
} else if(x==2) {
if(y==1) {
return tiletwo1;
} else if(y==2) {
return tiletwo2;
} else if(y==3) {
return tiletwo3;
} else if(y==4) {
return tiletwo4;
} else if(y==5) {
return tiletwo5;
} //......
} //......
The problem is it would take way too long to write this for every tile.
I need a function that will return a Tile object based on the x and y input of the Object Player. Any other solution would be great as well.
Tile getTileBasedOnCoords(int x, int y){
}
There are multiple ways to achieve this. The easiest seems to be (given the question) is by putting all Tile objects into the array, and returning the one with corresponding index.
Use a map with custom keys providing x and y values. This way you have direct access to the tile without the need to compare each tile with the player position (see getSectorByCoordinate() in the following code taken from a project of mine).
struct CSectorCoordinate
{
private:
int mX;
int mY;
public:
CSectorCoordinate();
CSectorCoordinate(int aX, int aY);
bool operator() (const CSectorCoordinate & a, const CSectorCoordinate & b) const;
int getX();
int getY();
};
...
bool CSectorCoordinate::operator() (const CSectorCoordinate & a, const CSectorCoordinate & b) const
{
// note: the following conditions ensure a strict weak ordering (see documentation of std::map)
if (a.mX < b.mX)
return true;
if (b.mX < a.mX)
return false;
return a.mY < b.mY;
}
...
typedef std::map<CSectorCoordinate, Configuration::CSectorEntity *, CSectorCoordinate> CSectorCoordinateMap;
CSectorCoordinateMap mSectorCoordinateMap;
...
bool CSectorEntityConfigurationBunch::getSectorByCoordinate(int aX, int aY, Configuration::CSectorEntity * & prSector)
{
CSectorCoordinateMap::const_iterator i(mSectorCoordinateMap.find(CSectorCoordinate(aX, aY)));
if (i != mSectorCoordinateMap.end())
prSector = i->second;
else
prSector = 0;
return prSector;
}