Help, looking for right tempalte/class declaration...

S

sccr13plyr

Hello,

I do not know if this forum is the right place to post this message.
If it is not, please let me know a better place to get my question
addressed. I am an old C programmer that became a self-taught C++
programmer. So, the following may simply be my ignorance of the C++
language.

I am at a site that has an older application written in C that has
over time been migrated to C++. This is a high performance
application that processes a 100 million records a day that are then
broken down into component transactions. We have a set of algorithms
that process these transactions and have a lot of duplicate logic.
We want to add functionality, simplify the code, and keep the
performance.

I prototyped out the following:

#include <stdio.h> // streams can be discussed another time... ;)

class BaseAlgorithm
{
public: virtual ~BaseAlgorithm (){}

public: inline void Display (const int id, const char* output)
{
(void) printf ("Algorithm: %d - %s\n", id, output);
}
};

template<int id, bool checkPrice, bool specificCode, bool currTran>
class GenericAlgorithm : public BaseAlgorithm
{
private: static const int algorithmId_ = id;
private: static const bool checkPriceChanged_ = checkPrice;
private: static const bool specificCode_ = specificCode;
private: static const bool currentTransOnly_ = currTran;

public: GenericAlgorithm (){}
public: virtual ~GenericAlgorithm (){}
public: inline void GenericLogic (int* data, int* env, char*
retInfo)
{
if (data == NULL)
if (env == NULL)
if (retInfo == NULL)
{
//
}

if (checkPriceChanged_)
{
if (specificCode_)
{
if (currentTransOnly_)
{
char v1[1000][1000];
v1[999][999] = 'd';
if (v1[999][999] == 'd')
{
}

Display (algorithmId_, "Check Price,
Specific Code, Current Tran");
}
else
{
Display (algorithmId_, "Check Price,
Specific Code, All Trans");
}
}
else
{
if (currentTransOnly_)
{
Display (algorithmId_, "Check Price, All
Code, Current Tran");
}
else
{
Display (algorithmId_, "Check Price, All
Code, All Tran");
}
}
}
else
{
if (specificCode_)
{
if (currentTransOnly_)
{
Display (algorithmId_, "Ignore Price,
Specific Code, Current Tran");
}
else
{
Display (algorithmId_, "Ignore Price,
Specific Code, All Trans");
}
}
else
{
if (currentTransOnly_)
{
Display (algorithmId_, "Ignore Price, All
Code, Current Tran");
}
else
{
Display (algorithmId_, "Ignore Price, All
Code, All Trans");
}
}
}
}
};

#include <stdlib.h>

int main (void)
{
GenericAlgorithm<159, true, true, true> test;
test.GenericLogic (NULL, NULL, NULL);

GenericAlgorithm<246, true, false, false> *oldTest = new
GenericAlgorithm<246, true, false, false>;
oldTest->GenericLogic (NULL, NULL, NULL);

return EXIT_SUCCESS;
}

This approach would collapse the three algorithms into one body of
logic in GenericLogic. By using constants, my desire is to have the
compiler create two separate versions of GenericLogic (one for each of
the new class declarations in main), removing code (and comparisons)
that would never need to be used.

Should I expect that the compiler is actually removing unreachable
code? Would this be compiler specific or I should be utilizing a
different C++ language construct? Also, the pointer declaration and
initialization becomes a little bulky, something I can do there?

Thanks in advance for your assistance, and sorry if this is not the
right venue...

sccr13plyr
 
M

Michael DOUBEZ

(e-mail address removed) a écrit :
[snip]
I am at a site that has an older application written in C that has
over time been migrated to C++. This is a high performance
application that processes a 100 million records a day that are then
broken down into component transactions. We have a set of algorithms
that process these transactions and have a lot of duplicate logic.
We want to add functionality, simplify the code, and keep the
performance.

After reading the code, you might consider refactoring quite a bit.
I would advice you to read (if not already done):
* Refactoring: Improving the Design of Existing Code
It will show you how to move around pieces of code
to fit and improve your design (what you are actually doing)
* Modern C++ Design Generic Programming and Design Patterns Applied
While a bit outdated concerning Loki, it will show you how
to use policies to achieve flexibility and simplification
for high performances.

I prototyped out the following:

#include <stdio.h> // streams can be discussed another time... ;)

Yes but it is however not the proper header:
#include said:
class BaseAlgorithm
{
public: virtual ~BaseAlgorithm (){}

public: inline void Display (const int id, const char* output)
{
(void) printf ("Algorithm: %d - %s\n", id, output);
}
};

Do you really need polymorhism on algorithm ? I would suggest you to
keep the algorithms orthogonal and make a type-erasure if you really
need polymorphic behavior.

I suspect that you want to do it to display data which is
counter-intuitive. Displaying data is usually part of the result of the
algorithm.

You can use a policy that manage result of algorithm:

//class to display algorithm information as a result of the algorithm
struct ResultDisplay
{
static void result(const int id, const char* result)
{
printf ("Algorithm: %d - %s\n", id, output);
}
};
template<int id, bool checkPrice, bool specificCode, bool currTran>

Using booleans if fine from a performance point of view, the compiler is
likely to optimize them out in GenericLogic but they do not carry the
intent of what you are doing and you will have to add other booleans for
other case.

In addition to that the logic might be difficult to debug. Here, I have
used PricingPolicy that indicate if the price is checked or not and a
SelectTransactionPolicy that indicate which transaction to select.

template
<int id
,class PricingPolicy
,class SelectTransactionPolicy
,class ResultPolicy = ResultDisplay
class GenericAlgorithm : public BaseAlgorithm
{
private: static const int algorithmId_ = id;
private: static const bool checkPriceChanged_ = checkPrice;
private: static const bool specificCode_ = specificCode;
private: static const bool currentTransOnly_ = currTran;

This is needed only if you are likely to use them in another template
construct. If not, don't do it; it just add maintaining and clutter.
public: GenericAlgorithm (){}
public: virtual ~GenericAlgorithm (){}
public: inline void GenericLogic (int* data, int* env, char*
retInfo)
{
if (data == NULL)
if (env == NULL)
if (retInfo == NULL)

if( data == NULL || env == NULL || retInfo == NULL )

Replace the following with orthogonal policies if possible.
An example with unique policy (Note: I don't know what specificCode and
currTran represent and how they interact or how to integrate them as
policy):

//Pricing policy
struct PriceNotChecked
{
static const char* check(const char* price)
{
return "Ignore Price";
}
};

struct PriceChecked
{
static const char* check(/* data */)
{
return "Check Price";
}
};

[snip] long code

ResultPolicy::result(id,PricePolicy::check());
}
};

#include <stdlib.h>

int main (void)
{
GenericAlgorithm<159, true, true, true> test;

GenericAlgorithm said:
test.GenericLogic (NULL, NULL, NULL);

GenericAlgorithm<246, true, false, false> *oldTest = new
GenericAlgorithm<246, true, false, false>;

GenericAlgorithm said:
oldTest->GenericLogic (NULL, NULL, NULL);

return EXIT_SUCCESS;
}

This approach would collapse the three algorithms into one body of
logic in GenericLogic. By using constants, my desire is to have the
compiler create two separate versions of GenericLogic (one for each of
the new class declarations in main), removing code (and comparisons)
that would never need to be used.

Should I expect that the compiler is actually removing unreachable
code?

Yes, but this code must be correct. I don't think you will have this
problem here.
Would this be compiler specific or I should be utilizing a
different C++ language construct?

I would expect main vendor compiler to do so depending on their option.
But checking does not hurt.
Also, the pointer declaration and
initialization becomes a little bulky, something I can do there?

Use a typedef.

If you need partial specialization, you can do the following (it will be
simplier under c++09):

template<int id>
struct OldAlgorithm
{
typedef GenericAlgorithm<id,PriceChecked,CurrentTransaction> type;

//helper to avoid writing new OldAlgorithm<id>::type(...)
static type* create(void* param1, void* param2, void* param3)
{
return new type(param1,param2,param3);
}
};

And then:

OldAlgorithm<246>::type* oldtest=
OldAlgorithm<246>::create(NULL,NULL,NULL);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top