Solved

simulate member templates in vc4.2

Posted on 1998-06-17
14
166 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
Comment Utility
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
Comment Utility
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
Comment Utility
That sounds like I'm writting you off.  If you need help ask.  I just suspected that you didn't.
0
 

Author Comment

by:eric_m
Comment Utility
> 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Free Trending Threat Insights Every Day

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.

 
LVL 11

Expert Comment

by:alexo
Comment Utility
Why don't you look at the sources to STLport.

0
 
LVL 2

Expert Comment

by:VEngineer
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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

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!

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
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…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now