Best practice C++ metaprogramming: logic flow - c++

Perhaps I've been spoiled by Ruby, but it seems to me that if I have two functions that use the same basic logic (but varying details), I should only have to write the logic out once -- and as a consequence, I should only have to maintain the code in one place.
Here is the basic logic, which I re-use in a number of different functions. The parts that change are labeled A, B, C, D, E, and F.
if (recursions) {
while (lcurr || rcurr) {
if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
// A
lcurr = lcurr->next;
} else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
// B
rcurr = rcurr->next;
} else { // keys are == and both present
// C
lcurr = lcurr->next;
rcurr = rcurr->next;
}
}
} else {
while (lcurr || rcurr) {
if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
// D
lcurr = lcurr->next;
} else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
// E
rcurr = rcurr->next;
} else { // keys == and both left and right nodes present
// F
lcurr = lcurr->next;
rcurr = rcurr->next;
}
}
}
The return values of the functions may be different, too. I'd like to be able to have additional logic as well in various places, if possible.
I realize that this can be done by way of C macros, but they don't seem particularly maintainable. I also realize that if my matrix type used nested STL lists, this might be easier. But is there any functionality in C++11 (or old C++) that allows this logic to be written only once? Could one do this with lambdas, perhaps?

The way I've seen this done is to write callback functions. So you would write the logic part once, much like you have in your second text block. You would also define functions A, B, C, D, E, and F.
In your logic function, you would pass in both the parameters required and pointers to the callback functions. Then, in the logic function, you would call these callbacks and pass them the parameters they need.
Quite honestly, this seems like it would be more work in the end. You would maintain a single point of truth for your logic, but function pointers can be a massive pain and reduce the readability of your code.
For the sake of providing as much information as possible, an example:
int addTwoNumbers(int a, int b) { //A simple adding function
return a + b;
}
int subtractTwoNumbers(int a, int b) { //A simple subtracting function
return a - b;
}
/*
* This is the fun one. The first argument is a pointer to a function. The other
* arguments are the numbers to do math with. They aren't as important.
* The important part is that, so long as the function declaration matches the one here
* (so a function that returns an int and takes in two ints as arguments) it can be
* used by this function
*/
void math(int (*mathFunc)(int, int), int one, int two) {
cout << *mathFunc(one, two);
}
int main(int argc, char* argv[]) {
int whichMath = 0; //Assume 1 is add, 2 is subtract
if(whichMath == 1) {
math(&addTwoNumbers, 5, 6); //we're going to add 5 and 6
} else {
math(&subtractTwoNumbers, 5, 6); // we're going to subtract 5 and 6
}
}
If that makes NO sense, then you are welcome to join the legions of us who struggle with function pointers. Again, I would say that you should just write the two separate functions, as you can see how ugly this will get.
As a disclaimer, I have not compiled this code. I'm at work and there is no c++ compiler on these machines.
I have used this site heavily in the past for reference on function pointers:
http://www.newty.de/fpt/fpt.html#defi

Well, one solution is to yank out the bit of redundant code and put it into a template, such as
template<T1, T2, T3>
bool TESTKEYS(T1 lcurr, T2 rcurr, T3 actor)
{
while (lcurr || rcurr) {
if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
if (actor.TestLeft(....)) return false;
lcurr = lcurr->next;
} else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
if (actor.TestRight(....)) return false;
rcurr = rcurr->next;
} else { // keys == and both left and right nodes present
if (actor.TestBoth(....)) return false;
lcurr = lcurr->next;
rcurr = rcurr->next;
}
}
return true;
}
You will need to decide for yourself what parameters to use for the TestLeft, etc.

template<typename A, typename B, typename C>
void compute (/*some parameters */)
{
if (recursions) {
while (lcurr || rcurr) {
if (!rcurr || (lcurr && (lcurr->key < rcurr->key))) {
auto aResult = A (lcurr, rcurr);
lcurr = lcurr->next;
} else if (!lcurr || (rcurr && (rcurr->key < lcurr->key))) {
auto bResult = B (lcurr, rcurr);
} // ... and so on
C (aResult, bResult);
} // ... etc
}
To call compute you need to write classes you want to pass down in place of your A to F placeholder. The actual work is done in the operator() member function of each class.
class A1 {
public:
double operator() (SomeType t1, SomeType t2) {
// do work
}
};
class A2 {
public:
int operator() (SomeType t1, SomeType t2) {
// do work
}
};
class B1 {
public:
char* operator() (SomeType t1, SomeType t2) {
// do work
}
};
class B2 {
public:
SomeClass* operator() (SomeType t1, SomeType t2) {
// do work
}
};
class C1 {
public:
int operator() (double t1, char* t2) {
}
class C2 {
public:
int operator() (int t1, SomeClass* t2) {
}
compute<A1, B1, C1>(whatever);
compute<A2, B2, C2>(whatever);
Note how A1 and B1 return types match C1 arguments, and similarly for A2, B2 and C2.
auto requires C++11, if you cannot use it, you will have to do a little additional work:
class A1 {
public:
typedef double result_type;
double operator() (SomeType t1, SomeType t2) {
// do work
}
};
and inside compute
typename A::result_type aResult = A (lcurr, rcurr);

Related

C++ How to reuse code of a (template) function, with different return type and slightly different behaviour?

I have a task to do (C++). I have quite a big function that have lot of arguments and uses a lot of different function inside. It is quite complicated. Overall, it creates a container and add values to the container depends on what is going on inside. I have to check if returned container is empty or to get its size but without calling that function with size() or empty(). (Not to create container only to check if it is empty()). I was told to create similar (almost identical) function that detects if there was something added to container. For example, something like this but with very easy example:
std::vector<int> getData(int& a, int& b, int& c) {
std::vector<int> result{};
//complicated operations replaced by simple to show a problem
for(int i=0;i<10;i++){
if(a - b > 0){
result.emplace_back(c);
}
else if ( c == 1){
return result;
}
else continue;
}
return result;
}
int getSize(int& a, int& b, int& c){
int size = 0;
//complicated operations replaced by simple to show a problem
for(int i=0;i<10;i++){
if(a - b > 0){
size++;
}
else if ( c == 1){
return size;
}
else continue;
}
return size;
}
As you can see, functions are almost identical. The real function is much bigger and code duplication is high. I am wondering if there might be a solution to that. I was told that templates might be good solution but I have no idea how should I use it. Can someone help me?
You could put the common part in a separate function template that takes a functor as an argument and supply different functors, like lambdas, inside your getData and getSize functions.
Example:
template <class Func>
void doStuff(int a, int b, int c, Func&& func) {
for (int i = 0; i < 10; i++) {
if (a - b > 0) {
func(); // call func(), the supplied functor
} else if (c == 1) {
return;
} else
continue;
}
return;
}
std::vector<int> getData(int& a, int& b, int& c) {
std::vector<int> result{};
// capture `result` and `c` in the lambda:
doStuff(a, b, c, [&result, c] { result.emplace_back(c); });
return result;
}
int getSize(int& a, int& b, int& c) {
int size = 0;
// capture `size` in the lambda:
doStuff(a, b, c, [&size] { ++size; });
return size;
}

Determine the 'owner' of an object

I want to determine which object 'owns' some other object.
I have a situation similar to the code below. Filling in the blanks, it compiles and seems to do what I expect - but will this work in general? Is there some idiomatic way to do this? Or is ill-advised altogether?
#include <functional>
#include <vector>
#include <iostream>
using namespace std;
struct A { int blah; /* ... */ };
struct B : A { /* ... */ };
struct C { vector<A> as{{}}; /*.. */ };
struct D { vector<C> cs{{}}; /*.. */ };
const A& superFoo(vector<reference_wrapper<const A>> alsoa) { alsoa.back();}
int main() {
B b{};
D d{};
const A& ds_a = /* Some selected 'a' from 'd' */;
vector<reference_wrapper<const A>> sfIn = {ref(b), ref(dads)};
auto out = superFoo(sfIn){ /* Some special selection process, based on A's attributes. */};
void* address = reinterpret_cast<void*>(&out);
/* Here I want to attribute which object, b or d, 'owns' the returned 'a' - 'out' */
if (address < reinterpret_cast<void*>(&b) + sizeof(b) &&
address >= reinterpret_cast<void*>(&b))
{ cout<< "b";
if (address < reinterpret_cast<void*>(&d) + sizeof(D) &&
address >= reinterpret_cast<void*>(&b))
{ cout<< "d"; }
}
The problem that you have is that each of the struct A through D all are composited in memory. Honestly, the real problem here is, how on earth do you come up with that pointer you are feeding to superfoo to begin with? If it came from one of your objects, then can you not tag it as such.
That's really a design problem. In general, C++ simply isn't designed to determine if an object is in a particular graph, but if you must, then:
To do this correctly, you would need to define something like so:
(Warning, this is off the top of my head)
struct PlainOldDataOnly
{
bool isMe(char *x) { return x >= (char *)this && x < (char *)this + sizeof(PlainOldDataOnly); }
}
struct HasVectors : PlainOldDataOnly
{
vector<myPlainOldData> stuff;
bool isMe(char *x) { return PlainOldDataOnly::isMe(x) || (x >= (char *)stuff.data() && x < (char *)(stuff.data() + stuff.size()); }
}
Note that in HasVectors, you would have to have that construct of stuff for every vector, and then, it could only work if and only if:
a) The vector(s) consists of only plain old data.
b) The vector(s) are not resized.
As others have said, this is very brittle code. The moment you put a map, a string, or something else into the objects in the vector, then you will run into problems. This would be a real pain to maintain.

How can a lambda capture itself for an asynchronous call?

I have to make an asynchronous call inside a lambda, and once the asynchronous call is terminated I have to call the lambda itself.
I try to explain my problem with code:
typedef function<void(int id)> Callback;
AsyncWork1(Callback call, int id, string)
{
//...
call(id);
}
AsyncWork2(Callback call, int id, double, string)
{
//...
call(id);
}
void AsyncWorks(Callback final_callback, int id)
{
Callback lambda = [&lambda, final_callback, id](int next_work) -> void
{
if(next_work == 1)
{
//...
AsyncWork1(lambda, 2, "bla bla");
}
else if(next_work == 2)
{
//...
//the lambda variable no longer exists
AsyncWork2(lambda, 3, 0.0, "bla bla");
}
else if(next_work == 3)
{
//...
final_callback(id);
}
};
lambda(1);
}
int main()
{
AsyncWorks(...);
AsyncWorks(...);
AsyncWorks(...);
AsyncWorks(...);
return 0;
}
The problem is that when the code exits from "AsyncWorks(...)" function, the local variable "lambda" no longer exists.
I've read several threads that talk about lambda recursive, but I haven't found any solution.
How can I solve this problem?
The basic problem is that C++ doesn't expose the this pointer of a lambda to itself.
As it happens, there are many languages where during something's definition, you cannot refer to itself. This is fixed in functional languages using a technique called the "Y Combinator".
A simple y combinator in C++ looks like:
template<class F>
struct y_combinator_t {
F f;
template<class...Args>
auto operator()(Args&&...args)
-> std::result_of_t< F&( y_combinator_t<F>&, Args&&... ) >
{
return f( *this, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator_t<std::decay_t<F>> y_combinate( F&& f ) {
return {std::forward<F>(f)};
}
I'm of two minds if we should f( *this or f( f, I sometimes do either.
Use:
void AsyncWorks(Callback final_callback, int id)
{
Callback lambda = y_combinate(
[final_callback, id]
(auto& self, int next_work)
-> void
{
if(next_work == 1) {
//...
AsyncWork1(self, 2, "bla bla");
} else if(next_work == 2) {
//...
//the lambda variable no longer exists
AsyncWork2(self, 3, 0.0, "bla bla");
} else if(next_work == 3) {
//...
final_callback(id);
}
}
);
lambda(1);
}
basically, I added an implicit self parameter to the lambda function body. Caller of the operator() don't see this parameter.
Y combinator based off this post by myself with modifications.
Lambda can capture itself implicitly. To demo how? see below code it calculate factorial value.
#include <iostream>
int (* factorial)( const int) = []( const int number)
{
if( number > 1)
{
return number* factorial( number - 1);
}
else
{
return 1;
}
};
int main(int , char *[])
{
int fact = factorial( 7);
std::cout<< "7! = "<< fact<< std::endl;
}
Output 7! = 5040
If any variable is used inside lambda then lambda captures it implicitly, if it is not captured explicitly. Due to this inside lambda, name factorial referring itself, is available.
But if in place ofint (* factorial)( const int) = []( const int number){//implementation }; if auto is used like as follows,auto factorial = []( const int number){ //implementation };then g++ compiler gives following error,error: use of ‘factorial’ before deduction of ‘auto’
return number* factorial( number - 1);It is because type of factorial is not deduced, auto does not deduce for same control block. Name factorial will be available only below the declaration in case of auto.
#Yakk
To understand your answer I had to spend some time studying many c++ features, value category, rvalue, lvalue, move constructor, move assignment operator, variadic templates, variadic templates with implicit conversions, result_of_t<>, decay_t<>, forward<>.
But I don't have a thing yet, why did you put the '&' symbol here?
... std::result_of_t <F&(y_combinator_t<...
I also rewrote your solution to make it more specific for my case and easier to read and understand for me too (and for all those who are beginners with C++),
class y_combinator_t
{
public:
function<void(y_combinator_t*, int, double, string)> callback;
void operator()(int a, double b, string s)
{
this->callback(this, a, b, s);
}
};
y_combinator_t combinator = {
[id_work = 1]
(y_combinator_t* _this, int a, double b, string s) mutable -> void
{
if(id_work == 1)
{
//...
AsyncWork1(*_this, 2, 3.0, "bla bla");
id_work = 2;
}
else if(id_work == 2)
{
//...
AsyncWork2(*_this, 3, 0.0, "bla bla");
id_work = 3;
}
else if(id_work == 3)
{
//...
}
}
};
//Start works
combinator(0, 0, "");

Optimizing loop and avoiding code duplication in a template specialization

Assume we have a function
template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
BOOST_FOREACH(const A& key, keyContainer)
{
B* pVal = someGetObjFunction(objPointer, key);
if(pVal)
{
if(selector && selector(*pVal))
{
pVal->someOtherFunction(1,2,3);
}
//some more code
}
}
}
This looks bad because it will always enter the
if(selector && selector(*pVal))
even when it is NULL, an obvious approach to fix this would be :
template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
if(selector)
{
BOOST_FOREACH(const A& key, keyContainer)
{
B* pVal = someGetObjFunction(objPointer, key);
if(pVal)
{
if(selector(*pVal))
{
pVal->someOtherFunction(1,2,3);
}
//some more code
}
}
}
else
{
BOOST_FOREACH(const A& key, keyContainer)
{
B* pVal = someGetObjFunction(objPointer, key);
if(pVal)
{
pVal->someOtherFunction(1,2,3);
//some more code
}
}
}
}
But this resulted in a lot of code duplication, another approach would be making a specialization for the case when the function is NULL but wouldnt that be almost identical as the example above? Is there another way of doing that without duplicating all the code ?
Your problem description is a bit confusing. You are not checking for NULL, because selector is not a pointer. Instead, you are checking to see if the boost::function object is empty() see: http://www.boost.org/doc/libs/1_55_0/doc/html/boost/function.html#idp54857000-bb.
Also, your two blocks of code are not equivalent. Your seem to indicate that you want to execute the inner loop if either (selector is provided and true) or (selector is not provided).
So, your first code block should be:
template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
BOOST_FOREACH(const A& key, keyContainer)
{
B* pVal = someGetObjFunction(objPointer, key);
if(pVal)
{
if(!selector || (selector && selector(*pVal)))
{
pVal->someOtherFunction(1,2,3);
}
//some more code
}
}
}
This is logically equivalent to your second block of code.
As Igor Tendetnik mentioned, you need to actually measure the code to see where the bottleneck is. It's likely not the checking for selector being empty.
If checking to see if the selector is empty really is your bottleneck, which is unlikely because the compiler with optimizations turned on is going to make those comparisons very fast inlined function calls, you could cache the result of the empty test.
template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
bool check_selector = !selector.empty();
BOOST_FOREACH(const A& key, keyContainer)
{
B* pVal = someGetObjFunction(objPointer, key);
if(pVal)
{
if(!check_selector || (check_selector && selector(*pVal)))
{
pVal->someOtherFunction(1,2,3);
}
//some more code
}
}
}

Loop from one integer to another regardless of direction, with minimal overhead

Assume I'm given two unsigned integers:
size_t A, B;
They're loaded out with some random numbers, and A may be larger, equal, or smaller than B. I want to loop from A to B. However, the comparison and increment both depend on which is larger.
for (size_t i = A; i <= B; ++i) //A <= B
for (size_t i = A; i >= B; --i) //A >= B
The obvious brute force solution is to embed these in if statements:
if (A <= B)
{
for (size_t i = A; i <= B; ++i) ...
}
else
{
for (size_t i = A; i >= B; --i) ...
}
Note that I must loop from A to B, so I can't have two intermediate integers and toss A and B into the right slots then have the same comparison and increment. In the "A is larger" case I must decrement, and the opposite must increment.
I'm going to have potentially many nested loops that require this same setup, which means every if/else will have a function call, which I have to pass lots of variables through, or another if/else with another if/else etc.
Is there any tricky shortcut to avoid this without sacrificing much speed? Function pointers and stuff in a tight, often repeated loop sound extremely painful to me. Is there some crazy templates solution?
My mistake, originally misinterpreting the question.
To make an inclusive loop from A to B, you have a tricky situation. You need to loop one past B. So you work out that value prior to your loop. I've used the comma operator inside the for loop, but you can always put it outside for clarity.
int direction = (A < B) ? 1 : -1;
for( size_t i = A, iEnd = B+direction; i != iEnd; i += direction ) {
...
}
If you don't mind modifying A and B, you can do this instead (using A as the loop variable):
for( B+=direction, A != B; A += direction ) {
}
And I had a play around... Don't know what the inlining rules are when it comes to function pointers, or whether this is any faster, but it's an exercise in any case. =)
inline const size_t up( size_t& val ) { return val++; }
inline const size_t down( size_t& val ) { return val--; }
typedef const size_t (*FnIncDec)( size_t& );
inline FnIncDec up_or_down( size_t A, size_t B )
{
return (A <= B) ? up : down;
}
int main( void )
{
size_t A = 4, B = 1;
FnIncDec next = up_or_down( A, B );
for( next(B); A != B; next(A) ) {
std::cout << A << endl;
}
return 0;
}
In response to this:
This won't work for case A = 0, B = UINT_MAX (and vice versa)
That is correct. The problem is that the initial value for i and iEnd become the same due to overflow. To handle that, you would instead use a do->while loop. That removes the initial test, which is redundant because you will always execute the loop body at least once... By removing that first test, you iterate past the terminating condition the first time around.
size_t i = A;
size_t iEnd = B+direction;
do {
// ...
i += direction;
} while( i != iEnd );
size_t const delta = size_t(A < B? 1 : -1);
size_t i = A;
for( ;; )
{
// blah
if( i == B ) { break; }
i += delta;
}
What are you going to do with the iterated value?
If this is going to be some index in an array, you should use the relevant iterator or reverse_iterator class, and implement your algorithms around these. Your code will be more robust, and easier to maintain or evolve. Besides, a lot of tools in the standard library are built using these interfaces.
Actually, even if you don't, you may implement an iterator class which returns its own index.
You can also use a little bit of metaprogramming magic to define how your iterator will behave according to the order of A and B.
Before going further, please consider that this would only work on constant values of A and B.
template <int A,int B>
struct ordered {
static const bool value = A > B ? false: true;
};
template <bool B>
int pre_incr(int &v){
return ++v;
}
template <>
int pre_incr<false>(int &v){
return --v;
}
template <int A, int B>
class const_int_iterator : public iterator<input_iterator_tag, const int>
{
int p;
public:
typedef const_int_iterator<A,B> self_type;
const_int_iterator() : p(A) {}
const_int_iterator(int s) : p(s) {}
const_int_iterator(const self_type& mit) : p(mit.p) {}
self_type& operator++() {pre_incr< ordered<A,B>::value >(p);return *this;}
self_type operator++(int) {self_type tmp(*this); operator++(); return tmp;}
bool operator==(const self_type& rhs) {return p==rhs.p;}
bool operator!=(const self_type& rhs) {return p!=rhs.p;}
const int& operator*() {return p;}
};
template <int A, int B>
class iterator_factory {
public:
typedef const_int_iterator<A,B> iterator_type;
static iterator_type begin(){
return iterator_type();
}
static iterator_type end(){
return iterator_type(B);
}
};
In the code above, I defined a barebone iterator class going accross the values from A to B. There's simple metaprogramming test to determine whether A and B are in ascending order, and pick the correct operator (++ or --) to go through the values.
Finally, I also defined a simple factory class to hold begin and end iterators methods, Using this class let you have only one single point of declaration for your dependent type values A and B (I mean here that you only need to use A and B once for this container, and the iterators generated from there will be depending on these same A and B, thus simplifying code somewhat).
Here I provide a simple test program, outputing values from 20 to 11.
#define A 20
#define B 10
typedef iterator_factory<A,B> factory;
int main(){
auto it = factory::begin();
for (;it != factory::end();it++)
cout << "iterator is : " << *it << endl;
}
There might better ways of doing this with the standard library though.
The issue of using O and UINT_MAX for A and B was brought up. I think it should be possible to handle these cases by overloading the templates using these particular values (left as an exercise for the reader).
size_t A, B;
if (A > B) swap(A,B); // Assuming A <= B, if not, make B to be A
for (size_t i = A; A <= B; ++A) ...