implementation assistance

M

ma740988

Say I've got source executing on 2 processors. The prime difference
in the source lies in select member variables

So now consider:

# include <iostream>
# include <bitset>
using namespace std;

struct open_struct
{ int val1; int val2; };

#if 0
class foo { // foo for processor 1
open_struct open;
public:
foo(open_struct os)
:eek:pen(os)
{}
void test(int val)
{
std::bitset<24> bs(val);
for ( int idx(0); idx < bs.size(); ++idx )
{
if (bs[idx])
{
switch ( idx ) // i want bits 0 .. 3 here
{
case 0: cout << " bit 0 set " << endl; break;
case 1: cout << " bit 1 set " << endl; break;
case 2: cout << " bit 2 set " << endl; break;
case 3: cout << " bit 3 set " << endl; break;
break;
}
}
}
}
void do_work( int val ) { if ( val == os.val1 ) {} };
};


int main() // processor 1 main
{
open_struct os;
os.val1 = 0x200000; os.val2 = 5;
foo f;
f.test(0xFF);
}
#endif


class foo { foo for processor 2
open_struct open;

public:
foo(open_struct os)
: open(os)
{}
void test(int val)
{
std::bitset<24> bs(val);
for ( int idx(4); idx < 8; ++idx ) // i want bits 4 .. 7 here
{
if (bs[idx])
{
switch ( idx )
{
case 4: cout << " bit 4 set " << endl; break;
case 5: cout << " bit 5 set " << endl; break;
case 6: cout << " bit 6 set " << endl; break;
case 7: cout << " bit 7 set " << endl; break;
break;
}
}
}
}
void do_work(int val) { if ( val == os.val1 ) {} };
};

int main() // processor 2 main
{
open_struct os;
os.val1 = 0x100000; os.val2 = 5;

foo f(os);
f.test(0xFF);
}

Currently I'm maintaing two foo - classes - which _quite frankly_ is a
maintanence nightmare. Notice the bit range in foo::test is different
for the two classes in addition. I'm seeking to generate a generic
solution such that I'll have 1 foo class that'll handle the unique
range for each foo class. A template solution I'm not sure will help
me here.

Thanks in advance.
 
D

davidrubin

ma740988 said:
Say I've got source executing on 2 processors. The prime difference
in the source lies in select member variables

So now consider:

# include <iostream>
# include <bitset>
using namespace std;

struct open_struct
{ int val1; int val2; };

#if 0
class foo { // foo for processor 1
open_struct open;
public:
foo(open_struct os)

'os' should be passed by non-modifiable reference. Otherwise, you are
making extra copies, which is not efficient.
:eek:pen(os)
{}
void test(int val)
{
std::bitset<24> bs(val);
for ( int idx(0); idx < bs.size(); ++idx )
{
if (bs[idx])
{
switch ( idx ) // i want bits 0 .. 3 here
{
case 0: cout << " bit 0 set " << endl; break;
case 1: cout << " bit 1 set " << endl; break;
case 2: cout << " bit 2 set " << endl; break;
case 3: cout << " bit 3 set " << endl; break;
break;
}
}
}
}
void do_work( int val ) { if ( val == os.val1 ) {} };
};


int main() // processor 1 main
{
open_struct os;
os.val1 = 0x200000; os.val2 = 5;
foo f;
f.test(0xFF);
}
#endif


class foo { foo for processor 2
open_struct open;

public:
foo(open_struct os)
: open(os)
{}
void test(int val)
{
std::bitset<24> bs(val);
for ( int idx(4); idx < 8; ++idx ) // i want bits 4 .. 7 here
{
if (bs[idx])
{
switch ( idx )
{
case 4: cout << " bit 4 set " << endl; break;
case 5: cout << " bit 5 set " << endl; break;
case 6: cout << " bit 6 set " << endl; break;
case 7: cout << " bit 7 set " << endl; break;
break;
}
}
}
}
void do_work(int val) { if ( val == os.val1 ) {} };
};

int main() // processor 2 main
{
open_struct os;
os.val1 = 0x100000; os.val2 = 5;

foo f(os);
f.test(0xFF);
}

Currently I'm maintaing two foo - classes - which _quite frankly_ is a
maintanence nightmare. Notice the bit range in foo::test is different
for the two classes in addition. I'm seeking to generate a generic
solution such that I'll have 1 foo class that'll handle the unique
range for each foo class. A template solution I'm not sure will help
me here.

Just move the specialized part into the interface:

int test(int value, int begin, int end);
// Test bits of the specified 'value' in the range specified by
// '(begin, end]', and write to the standard output, for each
bit,
// if the bit is set. Return the number of bits set. The
behavior
// is undefined unless 'begin <= end'.

Then, you can specialize the call for each specific platform. This
signature and contract is more robust, and is better designed for
testing. To really push the envelope, 'test' should take an
'std::eek:stream' as an argument, rather than hardcoding 'std::cout'.
 
M

ma740988


Just move the specialized part into the interface:

int test(int value, int begin, int end);
// Test bits of the specified 'value' in the range specified by
// '(begin, end]', and write to the standard output, for each
bit,
// if the bit is set. Return the number of bits set. The
behavior
// is undefined unless 'begin <= end'.
Well, I'm doing a _lot_ more than just 'couts'. Cout's is only shown
here for illustration purposes.

With respect to a generic solution, I'm not seeing how that'll help me
get around the hard coded values;

for ( idx (begin) ; begin < end; ++begin )
{
if (bs[ begin ] )
{
// nwo i have to determine if it's 0 .. 3 (in one case) ( 4.. 8)
in the next
}
}
 
D

davidrubin

ma740988 said:

Just move the specialized part into the interface:

int test(int value, int begin, int end);
// Test bits of the specified 'value' in the range specified by
// '(begin, end]', and write to the standard output, for each
bit,
// if the bit is set. Return the number of bits set. The
behavior
// is undefined unless 'begin <= end'.
Well, I'm doing a _lot_ more than just 'couts'. Cout's is only shown
here for illustration purposes.

With respect to a generic solution, I'm not seeing how that'll help me
get around the hard coded values;

for ( idx (begin) ; begin < end; ++begin )
{
if (bs[ begin ] )
{
// nwo i have to determine if it's 0 .. 3 (in one case) ( 4.. 8)
in the next
}
}

You don't need to switch on the index. You already know the value:

for (int i = begin; i < end; ++i) {
if (bs) {
std::cout << "bit " << i << " is set: << std::endl;
}
}
 
M

ma740988

You don't need to switch on the index. You already know the value:

for (int i = begin; i < end; ++i) {
if (bs) {
std::cout << "bit " << i << " is set: << std::endl;
}
}

Right but if the range is 4 (begin) .. 8(end) and I need to do specific
things when i is 4 versus 5, 6 and 7. I need more than just 'begin'
and end for a generic solution.
 
K

Kai-Uwe Bux

ma740988 said:

Just move the specialized part into the interface:

int test(int value, int begin, int end);
// Test bits of the specified 'value' in the range specified by
// '(begin, end]', and write to the standard output, for each
bit,
// if the bit is set. Return the number of bits set. The
behavior
// is undefined unless 'begin <= end'.
Well, I'm doing a _lot_ more than just 'couts'. Cout's is only shown
here for illustration purposes.

With respect to a generic solution, I'm not seeing how that'll help me
get around the hard coded values;

for ( idx (begin) ; begin < end; ++begin )
{
if (bs[ begin ] )
{
// nwo i have to determine if it's 0 .. 3 (in one case) ( 4.. 8)
in the next
}
}


What about putting the code that varies into a function object that you
could either (a) create from the range boundaries or (b) just pass as a
parameter? The following code illustrates (a):

#include <iostream>
#include <bitset>
#include <functional>
#include <algorithm>
#include <cassert>

struct open_struct {
int val1;
int val2;
};


class TestAction : std::unary_function<bool,void> {

unsigned int counter;
unsigned int start_index;

public:

TestAction ( unsigned int start )
: counter ( 0 )
, start_index ( start )
{}

void operator() ( bool flag ) {
if ( flag ) {
std::cout << " bit " << start_index + counter << " is set\n";
}
++ counter;
}

}; // TestAction

class foo {

open_struct open;

public:

foo ( open_struct const & os )
: open ( os )
{}

void test ( int val, unsigned int beg, unsigned int end )
{
std::bitset<24> bs ( val );
assert( beg <= end );
assert( end <= 24 );
TestAction action ( beg );
for ( unsigned int index = beg; index < end; ++index ) {
action( bs[index] );
}
}

};


int main ( void ) {
open_struct os;
os.val1 = 0x200000; os.val2 = 5;
foo f ( os );
f.test(0xFF, 4, 8 );
}


Note that the TestAction object keeps track of the number of calls. This is
a little hacky. However, it allows you to say something like

switch ( counter ) {
case 0 : ...

}


Best

Kai-Uwe Bux
 
D

davidrubin

ma740988 said:
You don't need to switch on the index. You already know the value:

for (int i = begin; i < end; ++i) {
if (bs) {
std::cout << "bit " << i << " is set: << std::endl;
}
}

Right but if the range is 4 (begin) .. 8(end) and I need to do specific
things when i is 4 versus 5, 6 and 7. I need more than just 'begin'
and end for a generic solution.


One possibility is to pass a vector of callback functions.
 

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,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top