I have this section in my code where I am using an if else, and the ternary operator on the same bool condition. Is there a more elegant way to do this?
bool UseGroups //input parameter to a function.
std::vector<std::vector<int>>& relevantGamesGroup = (useGroups) ? (objFlight.gamesGroup[dayIndex]) : (objFlight.gamesSubGroups[dayIndex]);
if (useGroups) {
numberOfGroups = objFlight.numberOfGroups[dayIndex];
}
else {
numberOfGroups = 2 * (objFlight.numberOfGroups[dayIndex]);
}
I would probably write it like this, because I find it quite clear to read:
auto& relevantGamesGroup = useGroups
? objFlight.gamesGroup[dayIndex]
: objFlight.gamesSubGroups[dayIndex];
auto numberOfGroups = useGroups
? objFlight.numberOfGroups[dayIndex]
: objFlight.numberOfGroups[dayIndex] * 2;
If you need to use the variables relevantGamesGroup and numberOfGroups after only having checked the condition once, you could create and call a temporary lambda that you make return the necessary pair:
auto&& [relevantGamesGroup, numberOfGroups] =
[&]() -> std::pair<std::vector<std::vector<int>>&, int>
{
if (useGroups) return {objFlight.gamesGroup[dayIndex],
objFlight.numberOfGroups[dayIndex]};
return {objFlight.gamesSubGroups[dayIndex],
2 * objFlight.numberOfGroups[dayIndex]};
}();
// use relevantGamesGroup and numberOfGroups here
An alternative using the ternary/conditional operator instead of using a lambda:
auto&& [relevantGamesGroup, numberOfGroups] =
useGroups ? std::pair<std::vector<std::vector<int>>&, int>
{objFlight.gamesGroup[dayIndex],
objFlight.numberOfGroups[dayIndex]}
: std::pair<std::vector<std::vector<int>>&, int>
{objFlight.gamesSubGroups[dayIndex],
2 * objFlight.numberOfGroups[dayIndex]};
// use relevantGamesGroup and numberOfGroups here
If you use this kind of construct a lot, creating a helper function could simplify it:
#include <tuple>
template<class... Ts>
std::tuple<Ts...> ternary(bool cond, std::tuple<Ts...>&& True,
std::tuple<Ts...>&& False) {
return cond ? True : False;
}
You'd then supply the wanted types as template parameters and use structured bindings to extract the selected values / references just like above:
int main() {
int a1 = 1, b1 = 2, c1 = 3;
int a2 = 40, b2 = 50, c2 = 60;
auto&&[a,b,c] = ternary<int&,int&,int&>(true, {a1,b1,c1}, {a2,b2,c2});
std::cout << a << b << c << '\n';
++a; ++b; ++c; // these are references to a1, b1 and c1
std::cout << a1 << b1 << c1 << '\n';
}
Output:
123
234
With the types in your question, it could look like this:
void func(bool useGroups) {
auto&& [relevantGamesGroup, numberOfGroups] =
ternary<std::vector<std::vector<int>>&, int>(useGroups,
{objFlight.gamesGroup[dayIndex], objFlight.numberOfGroups[dayIndex]},
{objFlight.gamesSubGroups[dayIndex], 2 * objFlight.numberOfGroups[dayIndex]});
// use relevantGamesGroup and numberOfGroups here
}
Not sure whether it is more "elegant", but if you insist of writing only one if/else, then either use a pointer instead of reference for relevantGamesGroup which can be default-initialized and assigned later, or a lambda can help:
auto& relevantGamesGroup = [&]()->decltype(auto){
if (useGroups) {
numberOfGroups = objFlight.numberOfGroups[dayIndex];
return objFlight.gamesGroup[dayIndex];
} else {
numberOfGroups = 2 * (objFlight.numberOfGroups[dayIndex]);
return objFlight.gamesSubGroups[dayIndex];
}
}();
(Note that ->decltype(auto) is important here, since the lambda will otherwise return by-value, not by-reference.)
And for completeness the clearly worse way of doing it with just one ternary operator:
auto& relevantGamesGroup = useGroups
? ((void)(numberOfGroups = objFlight.numberOfGroups[dayIndex]),
objFlight.gamesGroup[dayIndex])
: ((void)(numberOfGroups = 2 * (objFlight.numberOfGroups[dayIndex])),
objFlight.gamesSubGroups[dayIndex]);
((void) cast optional if you are not using some very weird type for numberOfGroups)
This code looks fine to me. Here's how I would rewrite it, but it's mostly a matter of style.
bool useGroups;
// Use of auto
auto& relevantGamesGroup = useGroups ? objFlight.gamesGroup[dayIndex] : objFlight.gamesSubGroups[dayIndex];
numberOfGroups = objFlight.numberOfGroups[dayIndex];
if (useGroups) {
numberOfGroups *= 2;
}
This is clean and can be fixed by Joe the Intern if needed be.
using GroupGames = std::vector<std::vector<int>>;
GroupGames* relevantGamesGroup;
if (useGroups) {
relevantGamesGroup = &objFlight.gamesGroup[dayIndex];
}
else {
relevantGamesGroup = &objFlight.gamesSubGroups[dayIndex];
}
if (useGroups) {
numberOfGroups = objFlight->numberOfGroups[dayIndex];
}
else {
numberOfGroups = 2 * (objFlight->numberOfGroups[dayIndex]);
}
Or with the suggestion of #Ted Lyngmo below, it's even cleaner.
using GroupGames = std::vector<std::vector<int>>;
GroupGames* relevantGamesGroup = &objFlight.gamesSubGroups[dayIndex];
int numberOfGroups = 2 * (objFlight->numberOfGroups[dayIndex]);
if (useGroups) {
relevantGamesGroup = &objFlight.gamesGroup[dayIndex];
numberOfGroups = objFlight->numberOfGroups[dayIndex];
}
Related
suppose I want to assign a const variable based on complex calculations which depend on a conditional.
if the situation were simple, I could do:
const int N = myBool ? 1 : 2;
but it's more like
const int N = myBool ? <lengthy calculation> : <other lengthy calculation>;
What I'm doing is this, but I'd like something cleaner:
int N_nonconst;
if (myBool) {
N_nonconst = <lengthy calculation>;
}
else {
N_nonconst = <other lengthy calculation>;
}
const int N = N_nonconst;
obviously, I could also do this:
int possibility1 = <lengthy calculation>;
int possibility2 = <other lengthy calculation>;
const in N = myBool ? possibility1 : possibility2;
but I'd like to actually perform only one of those lengthy calculations.
If I were extending the language, I'd consider making something like a const_deferredAssignment declaration:
const_deferredAssignment int N;
if (myBool) {
N = <...>;
}
else {
N = <...>;
}
I could also wrap those calculations up in functions/methods, but they use a bunch of locals, so it would be a fairly verbose function call.
You could wrap each calculation in a lambda, and capture the local variables to reduce the verbosity of their arguments
{
// ...
auto firstFunc = [&]() -> int { ... };
auto secondFunc = [&]() -> int { ... };
const int N = myBool ? firstFunc() : secondFunc();
}
In this way only one of the two functions are actually executed.
You could move the lengthy calculations to a separate function:
int lengthCalculation()
{
if(myBool)
{
return <lengthy calculation>;
}
else
{
return <other lengthy calculation>;
}
}
const int N = lengthCalculation();
If you don't want to create a separate function that you can use a local lambda:
const int N = [&]()
{
if(myBool)
{
return <lengthy calculation>;
}
else
{
return <other lengthy calculation>;
}
}();
you could try and use
SWITCH(myBool)
{
Case 0 : first_lengthy_calculation
Break;
Case 1 : second_lengthy_calculation
Break;
}
In C++(*), is it possible to have a structure that "defers" some computation until needed (and maybe never does the computation if not necessary)? My use case is as follows: I have roughly a dozen bool variables, each of which is computed with some function call. Following that, there is a rather long (and complex) conditional statement that uses those bool variables in different combinations to determine what action the code will take next.
Here is some contrived sample code to hopefully better illustrate what I'm doing:
bool const b1 = func1(param1,param2,param3);
bool const b2 = func2(param4);
// ...
bool const b15 = func15(param35,param36,param37,param38);
if (b1 && !b5 && (b2 || b3)) { do_something1(); }
else if (b3 && !b15 || (b4 && b9 && b6)) { do_something2(); }
else if (b14 || b10 || (!b11 && b7)) { do_something3(); }
else if (b8) {
if (!b1 || !b6) { do_something4(); }
else if ( /* ... */ ) // ... etc
}
// ... and on and on
That is a purely contrived example, but hopefully it illustrates the idea.
Clearly this code could be re-written without the bools, and the functions called directly in the big conditional statement. But I feel that would make the already not-easy-to-read code even harder to read, and more error prone. And this logic could change, so I feel the bools make it easier to manage from a refactoring perspective as well.
Furthermore, any bool might be referenced multiple times within the conditional; so using the functions directly means execution could be duplicated. (I was thinking std::bind might get me there from a readability perspective; but it would still potentially call any of the funcN() calls multiple times.)
What I'm looking for is the best of both words, like a "deferred" compute. What if instead of being computed and assigned explicitly at the start of the code, I could say, "only evaluate these as needed (and remember the result)". The big conditional statement is such that, generally, not all bools actually need to be computed to determine what happens next. The goal here is improved performance, as this code is called often. So I'm trying to reduce the amount of work done on each iteration.
(*) Preferably C++14 (or older), as that's what my employer is using.
Edit: What about something like this:
#include <iostream>
#include <functional>
//////////////////////////////////////////////////////////////////////////////
class Sum
{
public:
int sum(int const a, int const b) { ++n_calls_; return (a+b); }
int getNCalls() const { return n_calls_; }
private:
int n_calls_ = 0;
};
//////////////////////////////////////////////////////////////////////////////
template <class BoundFunc, typename RetType>
class DeferredCompute
{
public:
DeferredCompute(BoundFunc const& f) : func_(f) { }
RetType operator()()
{
if (!computed_)
{
value_ = func_();
computed_ = true;
}
return value_;
}
private:
bool computed_ = false;
RetType value_;
BoundFunc const& func_;
};
//////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
Sum s;
auto boundSum = std::bind(&Sum::sum, &s, 75, 25);
DeferredCompute<decltype(boundSum), int> deferredSum(boundSum);
// call function directly repeatedly
for (int i=0; i<5; ++i)
{
std::cout << "boundSum()=" << boundSum() << std::endl;
}
std::cout << "s.getNCalls()=" << s.getNCalls() << std::endl;
// should only call once
for (int i=0; i<5; ++i)
{
std::cout << "deferredSum()=" << deferredSum() << std::endl;
}
std::cout << "s.getNCalls()=" << s.getNCalls() << std::endl;
return 0;
}
Output:
boundSum()=100
boundSum()=100
boundSum()=100
boundSum()=100
boundSum()=100
s.getNCalls()=5
deferredSum()=100
deferredSum()=100
deferredSum()=100
deferredSum()=100
deferredSum()=100
s.getNCalls()=6
std::async with the option std::launch::deferred is what you're looking for.
https://en.cppreference.com/w/cpp/thread/async
eg
auto future = std::async(std::launch::deferred, [](){return 5;});
// future isn't calculated yet
auto result = future.get();
// result = 5, and will remain cached while in scope.
At first, I would try using some lambda-closures.
const auto b1 = [&]() { return func1(param1,param2,param3); };
const auto b2 = [&]() { return func2(param4); };
// ...
const auto b15 = [&]() { return func15(param35,param36,param37,param38); };
if (b1() && !b5() && (b2() || b3())) { do_something1(); }
...
If you need to cache the bool results but not for the entire
lifetime of the program (static), this solution could
make it (three levels of lambda-closure; it's "Inception").
/**
g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
-pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#include <iostream>
void
test(int i)
{
auto cache=[](auto expr)
{
return [expr, res=false, done=false]() mutable
{
if(!done) { res=expr(); done=true; }
return res;
};
};
auto b1=cache([&]() { std::cout << "(eval b1)"; return i>2; });
auto b2=cache([&]() { std::cout << "(eval b2)"; return i<5; });
std::cout << "1: b1=" << b1() << " b2=" << b2() << '\n';
std::cout << "2: b1=" << b1() << " b2=" << b2() << '\n';
}
int
main()
{
for(int i=0; i<6; ++i)
{
std::cout << "~~~~~~~~\n";
test(i);
}
return 0;
}
/**
~~~~~~~~
1: b1=(eval b1)0 b2=(eval b2)1
2: b1=0 b2=1
~~~~~~~~
1: b1=(eval b1)0 b2=(eval b2)1
2: b1=0 b2=1
~~~~~~~~
1: b1=(eval b1)0 b2=(eval b2)1
2: b1=0 b2=1
~~~~~~~~
1: b1=(eval b1)1 b2=(eval b2)1
2: b1=1 b2=1
~~~~~~~~
1: b1=(eval b1)1 b2=(eval b2)1
2: b1=1 b2=1
~~~~~~~~
1: b1=(eval b1)1 b2=(eval b2)0
2: b1=1 b2=0
**/
For the sake of readability and maintainability you could organise the program as a state machine. That provides you with the benefit of separating the state transitions and actions from one another, plus it should be reasonably simple to rewire the logic later should the necessity arise.
See here for some examples:
C++ code for state machine
What if instead of being computed and assigned explicitly at the start of the code, I could say, "only evaluate these as needed (and remember the result)"
/// #brief only evaluate these as needed (and remember the result)
class lazy final
{
mutable std::future<bool> value_;
public:
template<typename Functor>
lazy(Functor &&f)
: value_{ std::async(std::launch::deferred,
std::forward<Functor>(f)) }
{
}
operator bool() const
{
return value_.get();
}
};
client code:
auto b1 = lazy::lazy{[&]{ return func1(param1,param2,param3); }};
auto b2 = lazy::lazy{[&]{ return func2(param4); }};
// ...
bool const b15 = lazy::lazy{[&]{ return func15(param35,param36,param37,param38); }};
// rest remains the same as your contrieved example
I have not compiled this code. If working in c++14 (as you mention) you may need a factory function similar to this:
template<typename Functor>
auto make_lazy(Functor&& f) { return lazy<Functor>(std::forward<Functor>(f)); }
The only thing that changes is the declaration of your bX variables. You may also consider adding code that tells you how often each lazy evaluation is called in practice, declaring those bX variables first, and launching them immediately, in parallel, instead of in a deferred manner. But only do that after you measure performance both ways.
Trying to understand lambdas in C++, what I do not understand is this:
int multiplier = 5;
auto timesFive = [multiplier](int a) { return a * multiplier; };
std::cout << timesFive(2) << '\n'; // Prints 10
multiplier = 15;
std::cout << timesFive(2) << '\n'; // Still prints 2*5 == 10 (???) - Should it be 30?
When the program calls the timesFive() the second time, I expect the result to be 30. But why is the result Still prints 2*5 == 10, not prints 2*15 == 30? Perhaps the lambda function somehow cannot track the value of multiplier, even though we have already tried to capture it?
And what is the way to get the desired result?
You captured multiplier by value, which means it was copied into the lambda. You need to capture it by reference:
int multiplier = 5;
auto timesFive = [&multiplier](int a) { return a * multiplier; };
std::cout << timesFive(2);
multiplier = 15;
std::cout << timesFive(2);
Lambdas are syntatic sugar for an unnamable class and the instance thereof. Sometimes expanding your code out to what this unnamable class can help understanding what is going on.
[ capture_list ]( arg_list ) -> return_value_clause_opt { body };
becomes very roughly (pseudo-code):
struct anonymous_type {
capture_list;
auto operator()( arg_list ) const -> return_value_clause_opt {
body
}
anonymous_type( capture_list_in ):capture_list(capture_list_in) {}
};
If you list a variable in capture_list by its plain name, it is copied into a copy within the anonymous class.
So your timesFive became
struct __secret_name__ {
int multiplier;
int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};
It should be pretty clear that changing multiplier in the above code won't change the behavior of timesFive.
If you put a & in front of the name, a non-const reference is placed within the anonymous class.
struct __secret_name__ {
int& multiplier;
int operator()(int a) const { return a*multiplier; }
};
int multiplier = 5;
auto timesFive = __secret_name__{multiplier};
now, changing multiplier will change the behavior of timesFive, because timesFive holds a reference to multiplier, not a copy of it.
Some details skipped above for brevity. The name __secret_name__ is only for exposition. The member variables of the lamba are not actually public. The lambda being trivially constructible is implementation defined even if its data is. Etc.
Let define a structure parser :
struct parser {
int (*buffer_push_strategy)();
int (*escape_buffer_push_strategy)();
int (*do_callback_strategy)();
};
I have an initialization function :
int parser_init() {
if (some_condition) {
parser->buffer_push_strategy = buffer_push_strategy1;
parser->escape_buffer_push_strategy = escape_buffer_push_strategy1;
parser->do_callback_strategy = do_callback_strategy1;
}
else {
parser->buffer_push_strategy = buffer_push_strategy2;
parser->escape_buffer_push_strategy = escape_buffer_push_strategy2;
parser->do_callback_strategy = do_callback_strategy2;
}
return 0;
}
where the strategy functions are defined somewhere.
Ok, so my interest is to determine which strategy has been used when I write the unit tests. Any idea how to accomplish that?
I saw something on internet about is_pointer function from C++ 11, but I don`t think this would help me.
parser is a variable:
struct parserT {
int (*buffer_push_strategy)();
int (*escape_buffer_push_strategy)();
int (*do_callback_strategy)();
} parser;
If you want to know which the strategy is, you could use:
int strategy= (parser->buffer_push_strategy == buffer_push_strategy1) ? 1 : 2;
Perhaps, you prefer to store the strategy number:
int parser_init() {
if (some_condition) {
parser->buffer_push_strategy = buffer_push_strategy1;
parser->escape_buffer_push_strategy = escape_buffer_push_strategy1;
parser->do_callback_strategy = do_callback_strategy1;
return 1;
}
else {
parser->buffer_push_strategy = buffer_push_strategy2;
parser->escape_buffer_push_strategy = escape_buffer_push_strategy2;
parser->do_callback_strategy = do_callback_strategy2;
return 2;
}
}
Then, you could init the parser as:
const int STRATEGY= parser_init();
You can compare function pointers
if(p.buffer_push_strategy == buffer_push_strategy1)
See https://ideone.com/QQzL1c
In c++, I want to use conditionals when assigning values, for example:
int i = true && 5 || 3;
For example, using Lua you can write this:
i = true and 5 or 3
I am not sure that this is possible
Here is something that I tried:
#include "stdafx.h"
#include <iostream>
void main()
{
int test = (true && 5) || 1;
int test2 = (false && 6) || 2;
std::cout << "Test: " << test << std::endl << "Test2: " << test2 << std::endl;
for(;;);
}
C++ isn't Lua.
In Lua, true and 5 expression results in 5. That's simply how Lua works with boolean expressions.
And that's not how C++ works with boolean expressions. In C++, a boolean expression results in a boolean value. That is, either true or false.
If you want to select between two values based on a condition, we have an operator for that:
int i = true ? 5 : 3;
If the condition is true, you get the value before the :. If it's false, you get the value after the :.
I suspect you're looking for int test = true ? 5 : 1;
What you need is a conditional expression:
int i = true ? 2 : 5;
In this case i will be 2.
If we really wanted to, as of c++11 (which gives us the and and or keywords as a synonyms for && and ||), we could almost strong-arm the c++ compiler into compliance, and get it to compile this:
int x = when_true(b) and 5 or 6;
In order to do this we would need to provide some scaffolding:
#include <iostream>
struct maybe_int {
bool cond;
int x;
operator int() const { return x; }
};
int operator || (const maybe_int& l, int r) {
if (l.cond) return l.x;
return r;
}
struct when_true {
when_true(bool condition)
: _cond(condition)
{}
auto operator&&(int x) const {
return maybe_int { _cond, x };
}
bool _cond;
};
int main()
{
using namespace std;
auto b = false;
int x = when_true(b) and 5 or 6;
cout << x << endl;
return 0;
}
My suggestion would be that you don't try this kind of thing at work.