Solved

simulate member templates in vc4.2

Posted on 1998-06-17
14
172 Views
Last Modified: 2010-04-01
I'm using VC4.2, and what I really want to do is grant
friendship to a couple of template functions so I can
make my stream accessor method private, but VC4.2 does
not appear to support this.  (Well, what I *really*
wanted was template member functions, then I wouldn't
have them outside the class, but VC4.2 lacks this, as
well.)

I really don't want to define distinct marshalling
operators for all expected types, but I am also
uncomfortable with the stream object being accessible
to any client that wants to grab it.

Any ideas?


class foo
{
public:
  strstream& stream(){return *m_stream;}

private:
  strstream* m_stream;
};

template<class T>
RegistryArchive& operator>>(RegistryArchive& s, T& t)
{
  s.stream() >> t;
  // other processing snipped
  return s;
}

template<class T>
RegistryArchive& operator<<(RegistryArchive& s, const T& t)
{
  s.stream() << t << endl;
  // other processing snipped
  return s;
}

0
Comment
Question by:eric_m
  • 4
  • 4
  • 3
  • +2
14 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 1166062
I'm not 100% sure what it is you are trying to do.

But I'm wondering if you can make your template class enherit from a non-template class that is a friend on the foo class.  Then the template class can use base class to obtain access to the private members of foo.  (The base class will have to provided meber functions fot he things you want to access.)
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166063
If your example was a little more concrete, I could probably be a little more precise in my answer.  But I suspect that (Although it is obvious that you have been programming in C++ for only a few days (joke)) that you can evaluate and apply my suggestion with no help from me.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1166064
That sounds like I'm writting you off.  If you need help ask.  I just suspected that you didn't.
0
Complete VMware vSphere® ESX(i) & Hyper-V Backup

Capture your entire system, including the host, with patented disk imaging integrated with VMware VADP / Microsoft VSS and RCT. RTOs is as low as 15 seconds with Acronis Active Restore™. You can enjoy unlimited P2V/V2V migrations from any source (even from a different hypervisor)

 

Author Comment

by:eric_m
ID: 1166065
> I'm not 100% sure what it is you are trying to do.

I'm creating a class that contains a strstream.  (I realized that
my posted code was somewhat confused...the marshalling operators
should be returning foo references, instead of RegistryArchives.)
In client code, I want to be able to write something like the
following:

foo theStream;
theStream << "Whatever goes here" << endl
          << 42 << endl;

The foo object is basically a wrapper around the strstream that
keeps other state information, as well.  It will then be stored
for later retrieval (i.e. persistence.)  Then, I will want to
marshall the data back in...

string objString;
long objLong;
theStream >> objString;
theStream >> objLong;

Ideally, I would have liked to implement this as...

class foo
{
public:
  template<class T>
  foo& operator>>(T& t)
    {
      *m_stream >> t;
      // other processing snipped
      return *this;
    }

  template<class T>
  foo& operator<<(const T& t)
    {
      *m_stream << t << endl;
      // other processing snipped
      return *this;
    }

private:
  strstream* m_stream;
};

But, MSVC4.2 does not support member templates.  So, I can move
them out into free functions, and this works...but it leaves my
class having to expose its implementation.


> But I'm wondering if you can make your template class
> enherit from a non-template class that is a friend on
> the foo class.

Hopefully I've made myself a little more clear now.  The problem
is that I don't have a template class...I'm using template
functions.  Does this make a little more sense, or am I still
being confusing?

Thanks!


0
 
LVL 2

Expert Comment

by:VEngineer
ID: 1166066
I don't know your exact application, but there is a good middle ground:

You can make the operators auxillary "free functions" but have them call members of the class.  This will keep your implementation hidden.  Here is a partial example with a simple stream.  You can modify the rest to your specific app.

class Rational {
   public:
      Rational(int numer, int denom = 1) {
         NumeratorValue = numer;
         DenominatorValue = denom;
      }
     
      void Insert(ostream &out) const {
         out << NumeratorValue << '/' << DenominatorValue;
      }
     
      void Extract(istream &in) {
         int n;
         int d;
         char slash;
         
         in >> n >> slash >> d;

         NumeratorValue = n;
         DenominatorValue = d;
      }
      // other functions here
   private:
      int NumeratorValue;
      int DenominatorValue;

};  // end the class


// auxillary operator functions

ostream& operator<<(ostream& sout, const Rational& r) {
   r.Insert(sout);
   return sout;
}

istream& operator>>(istream& sin, Rational& r) {
   r.Extract(sin);
   return sin;
}
0
 
LVL 2

Expert Comment

by:VEngineer
ID: 1166067
For example, in the code fragment I wrote,
you can use it like:

void main() {

    Rational myFraction(1, 2);   // fraction is one-half
    cout << myFraction << endl;   // displays "1/2" on screen
    cin >> myFraction;    // read in a new value for ex: "1/8"
    cout << myFraction << endl;   // displays "1/8" on screen

}

Of course you can modify this thing to do other streams that iostream, but that is trivial.  Hope this helps.

You could also do friend functions too, but that also undermines the principle of information hiding.  If you want details on this method, let me know.
 
0
 

Author Comment

by:eric_m
ID: 1166068
In my case, I'm creating the stream and want to be able to use operator<< and operator>> to marshall data in and out of my stream.  I could define a member function *for each type* within my class, and then provide free functions *for each type* that use those member methods.  I really want to stay away from doing that, however.

0
 
LVL 11

Expert Comment

by:alexo
ID: 1166069
Why don't you look at the sources to STLport.

0
 
LVL 2

Expert Comment

by:VEngineer
ID: 1166070
Ok, I see exactly what you are trying to do.
This is a very tricky question...
From what I understand, the C++ language itself overloads the operators <<, >>, +, -, *, /, etc.. for each of the basic types, so it does it the long way (the way you are trying to avoid).

If you tried:

class foo <class T>
{
  friend foo& operator>>(foo& s, T& t);
  friend foo& operator<<(foo& s, const T& t);

public:
  // constructor and other
  // member functions
private:
  strstream* m_stream;
  strstream& stream(){return *m_stream;}
};

// now your friend functions have access to the private data members

template<class T>
foo& operator>>(foo& s, T& t)
{
  s.stream() >> t;
  // other processing snipped
  return s;
}

template<class T>
foo& operator<<(foo& s, const T& t)
{
  s.stream() << t << endl;
  // other processing snipped
  return s;
}

It will only work for one single type of T at a time for each instance of foo, so I guess you still have a problem here.

Nietod is right... a better solution may have to be inheritance and polymorhphism, but that does not appear to help in solving your original problem.


0
 
LVL 2

Expert Comment

by:VEngineer
ID: 1166071
The reason why C++ does not allow what you are trying to do is because all C++ containers must be homogenous.  Any container must contain the same type/class of elements.

Ex: you cannot create an array/user defined class of mixed types.

If there is a "simple" solution out there, I'm really interested in seeing it.
0
 
LVL 5

Expert Comment

by:yonat
ID: 1166072
You wrote:
    *m_stream >> t;
    // other processing snipped
    return *this;

This seems like the decorator pattern. Is that what you're looking for? If this is the case, just make your own streambuf class to do this, and let the stream class use this streambuf class. (streambuf handles the io, stream handles the formatting. So streambuf doesn't need to "know" about all the possible types.)

Please add a comment if you need more info about the stream-streambuf design, or about the decorator pattern, and I'll try to expand on these subjects.
0
 

Author Comment

by:eric_m
ID: 1166073
yonat:

> This seems like the decorator pattern. Is that what you're
> looking for?

Maybe...I haven't used that before, but it looks like that might
do the trick.  I actually may be able to get away without
implementing my own marshalling operators at all by using
decorator.  Let me try this...I'll have something by the end of
the day.

Thanks!

0
 

Author Comment

by:eric_m
ID: 1166074
Yonat:

The decorator was just what I needed.  Thanks so much!!

I had seen the decorator in gui contexts, but never thought about its applicability to streams.  GOF has a great example that shows  how to use it with streams.  Go ahead and "answer", and I'll give you an A.  :)
0
 
LVL 5

Accepted Solution

by:
yonat earned 300 total points
ID: 1166075
Thanks, eric_m. BTW, for example of deriving your own streambuf see http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/ and also http://www.snippets.org/#section1group30 .
0

Featured Post

Ransomware-A Revenue Bonanza for Service Providers

Ransomware – malware that gets on your customers’ computers, encrypts their data, and extorts a hefty ransom for the decryption keys – is a surging new threat.  The purpose of this eBook is to educate the reader about ransomware attacks.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

772 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