Solved

output template data

Posted on 2003-11-20
25
517 Views
Last Modified: 2010-04-02
I'd like to implement a print function that'll print the contents of  T msg[ 0 or 1 ].  In essence if  i call the "Store" function i could then call the print function to print the contents of what was stored, likewise the same for the retrieve function.  In retrospect I'd like to print T.  How would i achieve this?  

// template.h
enum BOOLEAN { FALSE = 0,
               TRUE};

template <class T>
class BUFFER
{
public:
 
  BUFFER();      
  ~BUFFER();  
  void            Store(unsigned char const* buffer);
  BOOLEAN         Retrieve(T& data);
  // T               Retrieve(T& data);  would this be more prudent ??
  int             Elements_Stored()    const;
  int             Elements_Retrieved() const;

private:

  static const int SIZE = 2;
  T msg [ SIZE ];    

  unsigned int store_count;        
  unsigned int store_index;
  unsigned int retrieve_count;    

  // override compiler defaults  
  BUFFER(BUFFER<T>& buffer);         // Copy construtor.
  void operator= (BUFFER<T>& rhs);   // Assignment operator
                                       
 
};

// Constructor
template<class T>
BUFFER<T>::BUFFER()
  : store_count(0), retrieve_count(0), store_index(1)
{
   memset( msg, 0, SIZE * sizeof(T));
}

// Destructor
template<class T>
BUFFER<T>::~BUFFER()
{
}

// store two items. the current and the previous
template<class T>
void BUFFER<T>::Store( unsigned char const* buffer)
{
  store_index ^= 1;
  // supposidely memcpy is bad news but std::copy benchmarked is slow
  // when compared to memcpy
  memcpy( &msg[store_index], buffer, sizeof(T));
  store_count++;     // increment the message stored count
}

// retrieve the most CURRENT item at ALL times
template<class T>
BOOLEAN BUFFER<T>::Retrieve(T& data)
{
  if (store_count > 0)  // here only to ensure the Retrieve never
                     // gets called the VERY FIRST TIME before the
Store
  {
    memcpy( &data, &msg[store_index], sizeof(T));
 retrieve_count++;
 return TRUE;
  }
  else
  {
 return FALSE;
  }
}
0
Comment
Question by:forums_mp
  • 12
  • 11
  • +1
25 Comments
 
LVL 15

Expert Comment

by:efn
Comment Utility
The usual approach is to require that a stream output operator for T be defined.  Then if ost is an ostream, you can code

ost << msg[0];

The operator function should be a free function declared like this:

ostream& operator <<(ostream& ostr, const someClass& obj);

--efn
0
 
LVL 1

Expert Comment

by:Hoegje
Comment Utility
As efn is saying : this should be in any of your possible T classes, if you want to make sure you can use the print function in your buffer with it.

In your template buffer class, you could write :

void Buffer::print(){
   std::cout << lastElementStored << std::endl;
}

but only if the type (T) of lastElementStored has an operator<< defined.

So suppose lastElementStored is a Complex type (class) :

ostream& Complex::operator<<(ostream& ostr, const someClass& obj){

ostr << obj.getRealPart;
ostr << " + ";
ostr << obj.getImaginarypart;
ostr << "i ";

return ostr;

}
0
 
LVL 4

Expert Comment

by:havman56
Comment Utility

// do new here
std::basic_ostream< T,std::char_traits<T> > *ostream_ptr= new ..()

(*ostream_ptr)<<msg[0];

where do u wnat to print ? on the console or file whatever may be if console use cout .if file
use filestream_ptr

whatever efn and hoe sayed is repeated in my comments
but ostream doesnt ahve any constructor whcih takes no parameter ..

u need streambuffer to construct ostream . so use new ... u cna acheive much easier.

otherwise use uninitialised() constructor
0
 

Author Comment

by:forums_mp
Comment Utility

A couple of things.
1. Yes, it'll be output to the console, though the filesream version also sounds interesting. Perhaps i could 'hack' away at both.

2. Currently i'm using std::printf for all output.  Had an issue with std::cout outputting values (value was of type char.  so now unsigned char xx[ 3 ] = { 1, 2 };)  but have yet to investigate why.  In part because i get the impression from a seemingly experienced veteran that std::cout does not work well in our console.   i suspect the veteran is wrong and i'm sure my issue was .. well me :).  in any event, could i achieve the same objective using 'std::printf"??
0
 
LVL 15

Assisted Solution

by:efn
efn earned 150 total points
Comment Utility
You can't do exactly the same thing with printf, in the sense that there is no %-something format specification that will work with an unknown type T.  What you can do, though, is require that T be able to represent itself in the form of a character string, which you can then put out.

For example:

class Whatever
{
public:
  std::string toString();
  ...
};

template<class T>
void BUFFER<T>::Print()
{
  printf("%s, %s\n", msg[0].toString().c_str(), msg[1].toString().c_str());
}

If you describe more about your problems with stream output to cout, somebody here can probably help you.

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

Yikes, i just realized that.  Just bumped into the chapter on operator overloading and saw the limitation.

Now say I have
unsigned char buffer [ 4 ] = { 12, 1, 15, 5 };

lets say:
unsigned char *ptr = buffer;

for (int idx = 0; idx < 4; idx++)
{
  // now print in  hex
  // printf( " value = %2X\n",  ptr[idx]);  // as a former C hacker printf WORKS!!

  std::cout << "value = " << std::hex << ptr[idx] << std::endl;  // doesnt work
}

The output on my console
value =
value =
value =
value =

I suspect cout doesnt like unsigned chars - in that contex - and i'm fighting my text but haven't discovered the issue yet.

lets say I had
struct  MYSTRUCT
{
   unsigned char aa;
   unsigned char bb;
   unsigned char cc;
   unsigned char dd;
};
MYSTRUCT mylocalstruct;

Lets suppose the contents of mylocalstruct is the same as above aa = 12, bb = 1, cc = 15, dd = 5

Short of doing individual print statements i.e
std::cout << " val = " << mylocalstruct.aa << std::endl;
std::cout << " val = " << mylocalstruct.bb << std::endl;
std::cout << " val = " << mylocalstruct.cc << std::endl;
std::cout << " val = " << mylocalstruct.dd << std::endl;

what's the ideal way to loop on and just output the values?
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
The first problem is just that when you put out a character to a stream, you get it literally, the equivalent of %c in printf.  If you want to see the numeric value, you just have to convert it to an integer, e.g., static_cast<int>(ptr[idx]).

For the second question, I can only suggest a vector or array with named subscripts, along these lines:

const int AA = 0;
// etc.

mylocalstruct.array[AA] = n;
// instead of mylocalstruct.aa = n;

for (int ndx = 0; ndx < MYSTRUCT_ARRAY_SIZE; ++ndx)
  std::cout << static_cast<int>(mylocalstruct.array[ndx]) << std::endl;

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

I was opting to write a sample program to perhaps answer a few items 1 and 2 but ..

/// 1.  The ostream opearator 'function' should be a 'friend' ?  
/// 2.  Could i place the ostream inside a 'print' function?  What i'm trying to figure out here is how would is how do i get visibility into the ostr object?   In other words,  i'm sitting in a while forever loop waiting for data.. when data arrives i process it, via store

void MY_CLASS::DoSomething()
{
    while (1)
    {
      unsigned char buffer [ 256 ];

      int retrieved = Read_Data( buffer, ... );
      if (retrieved != 0)
        buffer.Store ( buffer );
       // now i want to print all 256 (assume buffer returned 256) bytes.
       // how can i achieve this when i have no visibility into ostr??
    // or
       buffer.Retrieve ( localmsg );
       // now i want to print all 256 (assume 256) bytes.
       // same here.  how can i print ??
    }
}

///3  a question on the Store and Retrieve per the original code.  lets suppose Store is writing the contents of buffer into msg[0].  At the instant that Store is writing,Retrieve is copying the contents of msg[0] into data.  How could i prevent this short of using the features of the RTOS?
This of course assumes that the Store function had set the new_msg_available flag at least twice since they're now 'pointing' to the same index.

void BUFFER<T>::Store( unsigned char const* buffer)
{
  store_index ^= 1;
  memcpy( &msg[store_index], buffer, sizeof(T));
  new_msg_available = true;
  store_count++;     // increment the message stored count
}

// retrieve the most CURRENT item at ALL times
template<class T>
void BUFFER<T>::Retrieve(T& data)
{
    if (new_msg_available)
    {
        memcpy( &data, &msg[store_index], sizeof(T));
        retrieve_count++;
        new_msg_available = false;
    }
 }

/// 4  in the header file the operator equal would look like
BUFFER<T>& operator= (const BUFFER<T> rhs);
correct?

now how would the operator= look in the cpp file? i'm obviously missing something
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
/// 1.  The ostream opearator 'function' should be a 'friend' ?  

If it needs to access private or protected members, it should be a friend.  If it can do its job using only the public interface, it doesn't have to be a friend.

/// 2.  Could i place the ostream inside a 'print' function?  What i'm trying to figure out here is how would is how do i get visibility into the ostr object?

I don't think I understand what your problem is.  What kind of visibility do you think you need and why?

///How could i prevent this short of using the features of the RTOS?

You are in control of how many threads are using this code.  At least, I hope you are.  If only one thread is using it, you don't have to worry about this.  If more than one thread is using it, you will have to use the thread synchronization facilities of your target operating system.  There is nothing about threads in the C++ language itself.

/// 4  in the header file the operator equal would look like
BUFFER<T>& operator= (const BUFFER<T> rhs);
correct?

If that is intended to be inside the scope of the class declaration, it's OK.  It would be better to pass the parameter by reference, though.

///now how would the operator= look in the cpp file?

template<class T>
BUFFER<T>& BUFFER<T>::operator= (const BUFFER<T>& rhs)
{
  your code here
}

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

cant seem to get this to work.  toString() doesnt appear to be standard c++.  i'm using a gnu compiler.

template<class T>
void BUFFER<T>::Print()
{
  printf("%s, %s\n", msg[0].toString().c_str(), msg[1].toString().c_str());
}
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
toString() is not standard C++ in the sense that the language does not provide the function for you.  It is standard C++ in the sense that you can write your own.  Just as I was previously saying you had to provide an operator << function for the stream output design to work, for this design to work, you have to make sure that whatever class T you use with BUFFER has a toString member function.  If the compiler is complaining, I suspect it's because you have not provided this function.

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

I see.   so now
struct MSG_STRUCT
{
   unsigned char idx;
   unsinged char jdx;
}

struct MSG_STRUCT2
{
  MSG_STRUCT aa;
  unsinged char kk : 4;
}

void BUFFER<T>::toString<MSG_STRUCT2>( )
{
 //  i have an inclination on how to do this but i suspect i'll beg your assistance on MSG_STRUCT2
// ??
}

void BUFFER<T>::toString<MSG_STRUCT>( )
{
 
}

This sounds like a prime candidate for a map?  
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 15

Expert Comment

by:efn
Comment Utility
The toString functions should return a string.

The one for MSG_STRUCT2 can call the one for MSG_STRUCT to get a string representation of its aa component.

I don't see any need for a map.  How are you thinking of using a map?

--efn
0
 

Author Comment

by:forums_mp
Comment Utility
>> I don't see any need for a map.  How are you thinking of using a map?
Never mind :)  For some reason i thought perhaps when i called the print function i'd pass in the appropriate struct and have it print said struct but .. as you're well aware my C++ is  .. well

Could i get your take on the toString MSG_STRUCT2? using printf.

I'm starting to see where this would be much easier using the ostream operator but as you could perhaps tell i'd like to keep a 'C' version handy so we .. well
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
toString's job is to format a string, not to output anything to a string, so it would not be appropriate to use printf.  You could use sprintf.

char buf[200];

sprintf(buf, "aa = %s\nkk = %d\n", aa.toString().c_str(), kk);

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

efn  

>>toString's job is to format a string, not to output anything to a string
going nuts.  Write the toString for MSG_STRUCT2 for me?    


template<class T>
void BUFFER<T>::Print()
{
  //  printf("%s, %s\n", msg[0].toString().c_str(), msg[1].toString().c_str());
  sprintf(msg, "msg[0] = %d\n", msg[0].toString().c_str());

}

0
 
LVL 15

Accepted Solution

by:
efn earned 150 total points
Comment Utility
struct MSG_STRUCT2
{
  std:: string toString();

  MSG_STRUCT aa;
  unsinged char kk : 4;
};

std::string MSG_STRUCT2::toString()
{
  char buf[200];

  sprintf(buf, "aa = %s\nkk = %d\n", aa.toString().c_str(), kk);

  return std::string(buf);
}

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

so the end product toString would be wrapped in a print function that the outside world could call?

template<class T>
void BUFFER<T>::Print()  // this is questionable ??
{
  std::string MSG_STRUCT2::toString()
  {
     // stuff?
   }
}
 
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
Let us review.

You have a template class BUFFER.  You want to be able to tell a BUFFER to display its contents on the standard output stream.  This is non-trivial because BUFFER, being a template, does not know the type of the elements of its msg array.  So it can't directly use something like printf, because it doesn't know what kind of format specifications to use to format the text representation of an object of unknown type.

So BUFFER has to delegate at least formatting a T into text to the T class.  You have a choice here:  BUFFER can say to a T, "Expose yourself on standard output," or it can say "Give me a text representation of yourself."  If you choose the latter design, then after BUFFER gets a text representation, it can just send that text to standard output.

We have been discussing the second approach.  I named the member function that provides the text representation of an object "toString."  There is nothing standard or magical about this name; you could use any name you want, but to make it work, whatever you use as a T parameter to BUFFER has to provide whatever function BUFFER wants to call for string formatting.

Now to address your latest questions:

> so the end product toString would be wrapped in a print function that the outside world could call?

It's not exactly wrapped; a BUFFER client could call BUFFER<T>::Print() and that function could call T::toString to get some text to put out.

> template<class T>
> void BUFFER<T>::Print()  // this is questionable ??

Down to this point, it's fine.  The stuff below is questionable.  You can't nest a function inside a function.  Somewhere above on this page, I suggested some code for the Print function.  It calls the toString function of the objects in the msg array member of BUFFER.  So if you are dealing with BUFFER<MSG_STRUCT2>, then MSG_STRUCT2 must provide a toString member function, as I showed you in my immediately preceding comment.

--efn
0
 

Author Comment

by:forums_mp
Comment Utility
>> Expose yourself on standard output
I see.  In essense even if 'we' choose to the exposure method (which is the ostream version ?) then we still have to generate code for each struct.   Correct?
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
> I see.  In essense even if 'we' choose to the exposure method (which is the ostream version ?)

Not exactly, but it's closer than the toString design.  With toString, the object just provides a text representation of itself.  With the ostream design, it puts it out to any output stream.  The exposure method could take this a step further by building the selection of the standard output stream specifically into a member function.  This would make it a little more convenient for the BUFFER Print function, at the cost of some flexibility.

> then we still have to generate code for each struct.   Correct?

Yes, at least with the kind of design we have been discussing.

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

Bear with me one sec.  Just like to make sure i have all the 'cards'.   Lets talk ostream.  How could i use ostream where i dont have to generate code for each struct.

Here's my dilema.  I highlighted the designs you pointed out to a friend with which he concourred but claimed that with the current design, in either case i'd have to generate code for each structs.

So i thought well, if i change the desing how then can ostream work without generating code for each struct?
0
 
LVL 15

Expert Comment

by:efn
Comment Utility
Sorry if I was obscure.  When I said "with the kind of design we have been discussing," I meant all of the options, not just the toString design.  Your friend is right:  using ostreams would not change the need to write output code for every structure.

To avoid the need to write code for every structure, you would need much more exotic technology.  You would need a way to make the structures automatically self-describing.  I think you could do this with XML, but I don't know much about it.

--efn
0
 

Author Comment

by:forums_mp
Comment Utility

Understand.  Sorry it too me 'two+' attempts before it became clear to me :)
One question

if I have a class with a 'friend' XX with a friend YY

class YY; // forward declare YY
class XX
    class friend YY;
public:

};
Is it necessary to forward declare YY? Also the fact that YY is placed 'privately' in XX is irrelevant?

0
 
LVL 15

Assisted Solution

by:efn
efn earned 150 total points
Comment Utility
> Is it necessary to forward declare YY?

No.  The friend declaration is the equivalent of declaring YY at global scope.

> Also the fact that YY is placed 'privately' in XX is irrelevant?

Correct.

--efn
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now