Topic: Inline


Author: Dietmar Kuehl <dietmar.kuehl@claas-solutions.de>
Date: 1999/10/14
Raw View
Hi,
In article <7tkvdc$9rv$1@oravannahka.helsinki.fi>,
  Vesa A J Karvonen <vkarvone@cc.helsinki.fi> wrote:
> class Input_Stream
> {
> public:
>   virtual int Get()=0;
>
>   // Pure virtual interface
> };
>
> class Input_Stream_Buffer
>   : public Input_Stream
> {
>   Input_Stream& m_is;
>   char *m_buf_begin, *m_buf_current, *m_buf_end;
>   // ...
> public:
>   Input_Stream_Buffer(Input_Stream& is, int buf_size);
>
>   inline int Get()
>   {
>     // First tries getting a char from the buffer.
>     // If the buffer is empty, then fills the buffer
>     // by delegating to the given stream.
>   }
>
>   // ...
> };
>
> This kind of stream architecture is both highly flexible, through a
> couple of simple design patterns, esp. Adapter (139) and Decorator
> (175) (see Design Patterns), and highly efficient.

Probably I'm somewhat blinded but this looks very much like the standard
stream design to, except that the standard streams avoid a lot of
virtual function calls by doing the buffer handling in the base class.

> The standard stream architecture, which uses, IMHO, the poor C++ idiom
> of using a set of non-virtual inline functions that delegate to a set
> of virtual functions *in the same object* (see The C++ Programming
> Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
> significantly less flexible and also somewhat less efficient. The
> standard streams also suffer badly from other kinds of added
> responsibilities that could be implemented more flexibly and
> efficiently using the Decorator pattern. Based on my tests, the added
> responsibilities of both basic_streambuf and basic_istream result in a
> slowdown (reciprocal of speedup) of about a factor of 2-20 depending
> on the amount of data trasferred per transaction.

You keep stating that the standard IOStreams are slower than something.
I have not yet seen the alternative, neither an implementation (you
apparently have one, otherwise you could not measure such claims) or a
specification (if necessary, I could hack it myself). I have repeatedly
explained why most current implementation of IOStreams are slow and
described various techniques by which they can be improved. Since you
are still claiming that IOStreams are slow, I would like to see details
about the alternative so that I can make a reasonable evaluation of the
advantages and, if there are any, disadvantages of the approach you are
using. Also, I would like to compare my own implementation of the
standard iostream library to your approach to see whether it is really
slower. If it is, I would have to determine whether this is an inherent
problem with the specification or if it is just a sloppy implementation
missing some optimizations.

Since I/O is still important in many programs, I would like to create a
highly efficient mechanism to do I/O. Although there are some things
which appear to be rather inefficient in IOstreams at first sight, these
are normally in areas where the actual code can be optimized to
eliminate at least most of the overhead. As a result, my implementation
of IOStreams has a performance compareable to stdio: Sometimes there is
and advantage for stdio, sometimes for IOStreams but the difference is
less than 10% in all areas I have measured.

> #ifdef FEEL_LIKE_FLAMING
> Before you go on flaming me for bashing the standard stream
> architecture, I would suggest that you consider the following things:

Note, that I'm not flaming you. However, I doubt that your figures are
accurate and, due to a lack of the specification of your approach, I'm
not in the position to compare both approaches. Until I have seen what
you are doing, I claim that your ascertions about the efficiency of
standard IOStreams are plain false.

> - Is it not good practise to discuss the related anti-patterns when
> discussing the benefits of a pattern?

Sure it is good pratice to discuss related anti-patterns. However, you
are just claiming that these things are anti-patterns although they have
real advantage. The forwarding functions, for example, can be used to
determine unused virtual functions in compilers which don't support an
optimization to remove the definition of unused virtual functions. This
is, however, an important optimization for embedded systems. Thus,
before you claim that something is an anti-pattern, you should first
evaluate the advantages and disadvantages of a pattern. With respect to
the forwarding functions, I have yet to see an argument against them...

Of course, in this context you might argue that these forwarding
functions prevent the optimization of avoiding a virtual function call
if the most derived class is clear. For typical applications of the
stream buffers (this is where this stuff is going on) this is irrelevant
because these functions are called via a pointer to a 'streambuf' anyway
such that this optimization does not apply anyway. However, when
implementing a derived class, you and the implementation are free to add
extra inline function with the same name and behavior as those functions
in the base class, thereby making this optimization viable again.
For buffered streams there will be only a minor impact of this
optimization because most of the stuff is already handled inline in the
base class. For unbuffered streams like typical filtering stream buffers
there is possibly a significant advantage but I would guess that there
is even more advantage in turning these streams into buffered streams:
The operations working on stream buffers often make effective use of the
buffer.

> - Is there something that I was not correct about?

This is rather unclear to me: I claim there is indeed something you are
not correct about, namely the inefficiency of IOStreams. However, since
I cannot compare it against the stuff you are comparing it against, I
cannot really tell.

> - Do you think that it is better to shut up about problems than to
> expose them and suggest better alternatives?

It is fine to point out problems. However, I have not yet seen anything
which really identifies the stuff you are claiming as "problem". I guess
that you have indeed measured your stream approach against some
implementation of IOStreams. However, I can't tell which implementation
you used and I doubt that the implementation is fully optimized anyway.

Also, what you are suggesting as "better alternatives" are rather brief
excerpts of some aspects. I can show off highlights of IOStreams as well
and claim they are better alternives. But even showing how this stuff
might be implemented very efficient does not show anything: The context
and a reasonable coverage of typical use cases is also necessary to
determine whether something is really useful and can be implemented the
way it is claimed.

Concerning the example you have given, the inline 'get()' function in
the derive class, I claim that it either buys you nothing (because the
stuff is never inlined anyway) or produces a lot of code bloat (because
it has to be inlined all the time). You might argue that IOStreams also
have a lot of code bloat: This is true for most but not all
implementations of IOStreams. You can implement IOStreams without code
bloat.
--
<mailto:dietmar.kuehl@claas-solutions.de>
homepage: <http://www.informatik.uni-konstanz.de/~kuehl>


Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: postmast.root.admi.gov@iname.com (blargg) (postmaster@nospam.gov)
Date: 1999/10/14
Raw View
In article <7tt95l$77n$1@nnrp1.deja.com>, Dietmar Kuehl
<dietmar.kuehl@claas-solutions.de> wrote:

> Hi,
> In article <7tkvdc$9rv$1@oravannahka.helsinki.fi>,
>   Vesa A J Karvonen <vkarvone@cc.helsinki.fi> wrote:
> > class Input_Stream
> > {
> > public:
> >   virtual int Get()=0;
> >
> >   // Pure virtual interface
> > };
> >
> > class Input_Stream_Buffer
> >   : public Input_Stream
> > {
> >   Input_Stream& m_is;
> >   char *m_buf_begin, *m_buf_current, *m_buf_end;
> >   // ...
> > public:
> >   Input_Stream_Buffer(Input_Stream& is, int buf_size);
> >
> >   inline int Get()
> >   {
> >     // First tries getting a char from the buffer.
> >     // If the buffer is empty, then fills the buffer
> >     // by delegating to the given stream.
> >   }
> >
> >   // ...
> > };
> >
> > This kind of stream architecture is both highly flexible, through a
> > couple of simple design patterns, esp. Adapter (139) and Decorator
> > (175) (see Design Patterns), and highly efficient.
>
> Probably I'm somewhat blinded but this looks very much like the standard
> stream design to, except that the standard streams avoid a lot of
> virtual function calls by doing the buffer handling in the base class.

Yes. The iostream design adds a buffer in front of the virtual call,
essentially. The virtual call frequency is greatly reduced.

> > The standard stream architecture, which uses, IMHO, the poor C++ idiom
> > of using a set of non-virtual inline functions that delegate to a set
> > of virtual functions *in the same object* (see The C++ Programming
> > Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
> > significantly less flexible and also somewhat less efficient. The
> > standard streams also suffer badly from other kinds of added
> > responsibilities that could be implemented more flexibly and
> > efficiently using the Decorator pattern. Based on my tests, the added
> > responsibilities of both basic_streambuf and basic_istream result in a
> > slowdown (reciprocal of speedup) of about a factor of 2-20 depending
> > on the amount of data trasferred per transaction.

Of a *factor* of 2-20. That is wild!

> You keep stating that the standard IOStreams are slower than something.
> I have not yet seen the alternative, neither an implementation (you
> apparently have one, otherwise you could not measure such claims) or a
> specification (if necessary, I could hack it myself). I have repeatedly
> explained why most current implementation of IOStreams are slow and
> described various techniques by which they can be improved. Since you
> are still claiming that IOStreams are slow, I would like to see details
> about the alternative so that I can make a reasonable evaluation of the
> advantages and, if there are any, disadvantages of the approach you are
> using. Also, I would like to compare my own implementation of the
> standard iostream library to your approach to see whether it is really
> slower. If it is, I would have to determine whether this is an inherent
> problem with the specification or if it is just a sloppy implementation
> missing some optimizations.

See implementation below (but I suspect it virtually matches what you have
for your iostream implementation).

> Since I/O is still important in many programs, I would like to create a
> highly efficient mechanism to do I/O. Although there are some things
> which appear to be rather inefficient in IOstreams at first sight, these
> are normally in areas where the actual code can be optimized to
> eliminate at least most of the overhead. As a result, my implementation
> of IOStreams has a performance compareable to stdio: Sometimes there is
> and advantage for stdio, sometimes for IOStreams but the difference is
> less than 10% in all areas I have measured.

This is good! I don't like using much of the standard library currently
because the implementation is so bloated, in both compilation overhead and
run-time overhead. But the *interface* is well-designed, so it's just a
matter of maturity of implementation.

[snip]
> Concerning the example you have given, the inline 'get()' function in
> the derive class, I claim that it either buys you nothing (because the
> stuff is never inlined anyway) or produces a lot of code bloat (because
> it has to be inlined all the time). You might argue that IOStreams also
> have a lot of code bloat: This is true for most but not all
> implementations of IOStreams. You can implement IOStreams without code
> bloat.

Maybe I can deal with this issue. Here is what I consider to be a model
for an optimal implementation of the iostream get() (which gets the next
character) as compared to the virtual get() proposal.

inline get

    class optimal {
    public:
        optimal( std::size_t buffer_size );
        int get();
    protected:
        // for this example, derived class will bash these
        char* pos;
        char* end;
        char* buffer;
    private:
        virtual int refill() = 0;
        int empty();
    };

    inline int optimal::get() {
        if ( pos < end )
            return *pos++;
        return empty();
    }

    // an alternate implementation of get()
    // buffer must have an extra character allocated past end
    // could be more efficient because it involves one less branch
    inline int optimal::get() {
        int c = *pos++;
        if ( pos >= end )
            c = empty();
        return c;
    }

    optimal::optimal( std::size_t buffer_size ) :
            buffer( new char [buffer_size] )
    {
        // fill buffer
        pos = buffer;
        end = buffer + buffer_size;
    }

    // Take virtual call *out* of get(), since it will likely cause bloat.
    // The extra function call here is not a performance issue when
    // sufficient buffering is used.
    int optimal::empty() {
        return refill();
    }

    void user( optimal& stream ) {
        int c;
        while ( (c = stream.get()) != EOF ) {
            // ...
        }
    }

virtual get()

    class unoptimal {
    public:
        virtual int get() = 0;
    };

    void user( unoptimal& stream ) {
        int c;
        while ( (c = stream.get()) != EOF ) {
            // ...
        }
    }

The inline get version has optimal efficiency, in the case of a buffer
with data in it. In any case, it does the minimum necessary. If there is
data in the buffer (this requires a compare, obviously) it is read. If
there is not, the buffer is filled (efficiency isn't as critical for
this).

The virtual get() version requires a virtual *function call* for every
character, in addition to the equivalent of the above inline get function.
This is a non-trivial cost. Furthermore, it may limit a compiler from
keeping the buffer position and end in registers.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: postmast.root.admi.gov@iname.com (blargg) (postmaster@nospam.gov)
Date: 1999/10/14
Raw View
In article <7ttsso$qlc$1@oravannahka.helsinki.fi>, Vesa A J Karvonen
<vkarvone@cc.helsinki.fi> wrote:

> blarggpostmaster@nospam.gov <postmast.root.admi.gov@iname.com> wrote:
> > In article <7tkvdc$9rv$1@oravannahka.helsinki.fi>, Vesa A J Karvonen
> > <vkarvone@cc.helsinki.fi> wrote:
> [snip]
> > > This kind of stream architecture is both highly flexible, through a
> > > couple of simple design patterns, esp. Adapter (139) and Decorator (175)
> > > (see Design Patterns), and highly efficient.
>
> >     void f( Input_Stream& stream ) {
> >         while ( int i = stream.Get() ) {
> >             // ...
> >         }
> >     }
>
> > Involves a virtual call for every Get() operation. How is this more
> > efficient than the standard library iostreams, which (equivalently) inline
> > the Get() call and involve a virtual call only when the buffer is
> > refilled?
>
> You are already paying an extra cost in the streambuf, because the
> inline functions perform an extra conditional check before using the
> buffer.

What kind of conditional check?

As far as I know, the inline reading from a buffer first sees if the data
is in the buffer. I see no way of eliminating this from *any*
general-purpose variable-sized buffering scheme. If the buffer is empty,
then it is refilled.

> Furthermore, there is also the overhead of the six pointers
> reserved for buffering.

Overhead? If they aren't read, they aren't overhead for the get function.

> The buffering decorator approach is definitely faster when the compiler
> knows it is using the buffer decorator.

OK. You've waved this around enough. Show us the code.

> This happens quite often
> naturally. It is also easy to do it explicitly when it is known to be
> important.
>
> > > The standard stream architecture, which uses, IMHO, the poor C++ idiom
> > > of using a set of non-virtual inline functions that delegate to a set of
> > > virtual functions *in the same object* (see The C++ Programming
> > > Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
> > > significantly less flexible and also somewhat less efficient.
>
> > It's quite flexible while being optimally efficient for any stream type
> > (that uses buffering).
>
> First of all, the standard streambuf is not optimal even when the buffer
> is used. The extra conditional check guarantees that it is possible to
> do better.

Still don't know what this extra conditional check is.

> Second, like you implied yourself, if buffering isn't needed,
> then the extra buffering stuff, including the six pointers, is extra
> overhead.

Oh, wait, are you actually worrying about 6 pointers with regards to
memory overhead of the object containing the buffer?!? Whatever. This is
beyond my care. 24 bytes or so is not an issue.

> Many stream implementations intrinsically do not need
> buffering at all and could be made simpler if the implementation didn't
> have to collaborate with the public inline interface.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: postmast.root.admi.gov@iname.com (blargg) (postmaster@nospam.gov)
Date: 1999/10/11
Raw View
In article <7tkvdc$9rv$1@oravannahka.helsinki.fi>, Vesa A J Karvonen
<vkarvone@cc.helsinki.fi> wrote:

> srinivasa kolla <srinivasa.kolla@sabre.com> wrote:
>
> > Hi
> >    Can we define virtual functions as 'inline' functions.
> > Thanks for your reply.
> > Srinivas
>
> As the others have explained, it is possible.
>
> Defining a virtual function as inline in a derived class can be a very
> effective optimization. One particular instance where I've used it, is
> for making a buffering Decorator for a stream class. Consider the
> following snippets.
>
> class Input_Stream
> {
> public:
>   virtual int Get()=0;
>
>   // Pure virtual interface
> };
>
> class Input_Stream_Buffer
>   : public Input_Stream
> {
>   Input_Stream& m_is;
>   char *m_buf_begin, *m_buf_current, *m_buf_end;
>   // ...
> public:
>   Input_Stream_Buffer(Input_Stream& is, int buf_size);
>
>   inline int Get()
>   {
>     // First tries getting a char from the buffer.
>     // If the buffer is empty, then fills the buffer
>     // by delegating to the given stream.
>   }
>
>   // ...
> };
>
> This kind of stream architecture is both highly flexible, through a
> couple of simple design patterns, esp. Adapter (139) and Decorator (175)
> (see Design Patterns), and highly efficient.

    void f( Input_Stream& stream ) {
        while ( int i = stream.Get() ) {
            // ...
        }
    }

Involves a virtual call for every Get() operation. How is this more
efficient than the standard library iostreams, which (equivalently) inline
the Get() call and involve a virtual call only when the buffer is
refilled?

> The standard stream architecture, which uses, IMHO, the poor C++ idiom
> of using a set of non-virtual inline functions that delegate to a set of
> virtual functions *in the same object* (see The C++ Programming
> Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
> significantly less flexible and also somewhat less efficient.

It's quite flexible while being optimally efficient for any stream type
(that uses buffering).

> The
> standard streams also suffer badly from other kinds of added
> responsibilities that could be implemented more flexibly and efficiently
> using the Decorator pattern. Based on my tests, the added
> responsibilities of both basic_streambuf and basic_istream result in a
> slowdown (reciprocal of speedup) of about a factor of 2-20 depending on
> the amount of data trasferred per transaction.

Most implementations of iostreams aren't currently optimal.

[snip]
> Anyway, the real message to the original poster is that this kind of
> design, i.e. having *a virtual interface and an inline implementation*,
> can be a very powerful way to get both flexibility and efficiency.

I just don't see the latter in general, where the base class is passed
around by reference. It only happens when the complete type is known at
compile time. These cases don't occur when virtual functions are used
because they are necessary.

> This pattern isn't certainly limited to streams.

Certainly.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Vesa A J Karvonen <vkarvone@cc.helsinki.fi>
Date: 1999/10/12
Raw View
blarggpostmaster@nospam.gov <postmast.root.admi.gov@iname.com> wrote:
> In article <7tkvdc$9rv$1@oravannahka.helsinki.fi>, Vesa A J Karvonen
> <vkarvone@cc.helsinki.fi> wrote:
[snip]
> > This kind of stream architecture is both highly flexible, through a
> > couple of simple design patterns, esp. Adapter (139) and Decorator (175)
> > (see Design Patterns), and highly efficient.

>     void f( Input_Stream& stream ) {
>         while ( int i = stream.Get() ) {
>             // ...
>         }
>     }

> Involves a virtual call for every Get() operation. How is this more
> efficient than the standard library iostreams, which (equivalently) inline
> the Get() call and involve a virtual call only when the buffer is
> refilled?

You are already paying an extra cost in the streambuf, because the
inline functions perform an extra conditional check before using the
buffer. Furthermore, there is also the overhead of the six pointers
reserved for buffering.

The buffering decorator approach is definitely faster when the compiler
knows it is using the buffer decorator. This happens quite often
naturally. It is also easy to do it explicitly when it is known to be
important.

> > The standard stream architecture, which uses, IMHO, the poor C++ idiom
> > of using a set of non-virtual inline functions that delegate to a set of
> > virtual functions *in the same object* (see The C++ Programming
> > Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
> > significantly less flexible and also somewhat less efficient.

> It's quite flexible while being optimally efficient for any stream type
> (that uses buffering).

First of all, the standard streambuf is not optimal even when the buffer
is used. The extra conditional check guarantees that it is possible to
do better. Second, like you implied yourself, if buffering isn't needed,
then the extra buffering stuff, including the six pointers, is extra
overhead. Many stream implementations intrinsically do not need
buffering at all and could be made simpler if the implementation didn't
have to collaborate with the public inline interface.

---
Vesa Karvonen


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hyman Rosen <hymie@prolifics.com>
Date: 1999/10/08
Raw View
srinivasa kolla <srinivasa.kolla@sabre.com> writes:
>    Can we define virtual functions as 'inline' functions.

Yes, but inline expansion will happen only when the compiler can
determine the dynamic type of the object upon which the method call is
made. Generally this will mean that a call through a pointer or
reference will not be inline. To do better requires global analysis of
the entire program, not just one compilation unit.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/10/08
Raw View
On 7 Oct 1999 19:44:37 GMT, srinivasa kolla <srinivasa.kolla@sabre.com> wrote:

>   Can we define virtual functions as 'inline' functions.

Yes.

This is useful if the derived class virtual function calls the base class
virtual function and then does some stuff specific to the derived class.
Then if the base class function is inline (and optionally pure virtual),
then it could very well be inlined.

--
--------------
siemel b naran
--------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Vesa A J Karvonen <vkarvone@cc.helsinki.fi>
Date: 1999/10/08
Raw View
srinivasa kolla <srinivasa.kolla@sabre.com> wrote:

> Hi
>    Can we define virtual functions as 'inline' functions.
> Thanks for your reply.
> Srinivas

As the others have explained, it is possible.

Defining a virtual function as inline in a derived class can be a very
effective optimization. One particular instance where I've used it, is
for making a buffering Decorator for a stream class. Consider the
following snippets.

class Input_Stream
{
public:
  virtual int Get()=0;

  // Pure virtual interface
};

class Input_Stream_Buffer
  : public Input_Stream
{
  Input_Stream& m_is;
  char *m_buf_begin, *m_buf_current, *m_buf_end;
  // ...
public:
  Input_Stream_Buffer(Input_Stream& is, int buf_size);

  inline int Get()
  {
    // First tries getting a char from the buffer.
    // If the buffer is empty, then fills the buffer
    // by delegating to the given stream.
  }

  // ...
};

This kind of stream architecture is both highly flexible, through a
couple of simple design patterns, esp. Adapter (139) and Decorator (175)
(see Design Patterns), and highly efficient.

The standard stream architecture, which uses, IMHO, the poor C++ idiom
of using a set of non-virtual inline functions that delegate to a set of
virtual functions *in the same object* (see The C++ Programming
Language, 3rd. ed., 21.6.4 Stream Buffers, page 645) is typically
significantly less flexible and also somewhat less efficient. The
standard streams also suffer badly from other kinds of added
responsibilities that could be implemented more flexibly and efficiently
using the Decorator pattern. Based on my tests, the added
responsibilities of both basic_streambuf and basic_istream result in a
slowdown (reciprocal of speedup) of about a factor of 2-20 depending on
the amount of data trasferred per transaction.

#ifdef FEEL_LIKE_FLAMING
Before you go on flaming me for bashing the standard stream
architecture, I would suggest that you consider the following things:
- Is it not good practise to discuss the related anti-patterns when
discussing the benefits of a pattern?
- Is there something that I was not correct about?
- Do you think that it is better to shut up about problems than to
expose them and suggest better alternatives?
#endif

Anyway, the real message to the original poster is that this kind of
design, i.e. having *a virtual interface and an inline implementation*,
can be a very powerful way to get both flexibility and efficiency. This
pattern isn't certainly limited to streams.

---
Vesa Karvonen


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/10/09
Raw View
In article <37FCCEDE.4320B93B@sabre.com>, srinivasa kolla
<srinivasa.kolla@sabre.com> writes
>
>Hi
>   Can we define virtual functions as 'inline' functions.
>Thanks for your reply.
>Srinivas

AFAIK, yes, but it is unlikely that the compiler will do anything except
ignore the inline request for most calls through pointers/references
though it can inline direct calls (those that use the object)



Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Andrew R. Thomas-Cramer" <artc@prism-cs.com>
Date: 1999/10/09
Raw View
Yes, but there are costs.
  Other posters have already cited that a particular virtual method call
won't actually be inlined unless it's made on an _object_, not the pointers
and references used for most virtual function calls.
  In addition, a possible adverse interaction between compiler heuristics
and inlining all virtual functions in a class is noted by Scott Meyers in
"More Effective C++", item 24.

srinivasa kolla wrote in message <37FCCEDE.4320B93B@sabre.com>...
>
>Hi
>   Can we define virtual functions as 'inline' functions.
>Thanks for your reply.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: srinivasa kolla <srinivasa.kolla@sabre.com>
Date: 1999/10/07
Raw View
Hi
   Can we define virtual functions as 'inline' functions.
Thanks for your reply.
Srinivas




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/10/08
Raw View
srinivasa kolla <srinivasa.kolla@sabre.com> writes:

>   Can we define virtual functions as 'inline' functions.

Yes. Any function can be declared inline.

A virtual function in general needs to be callable via virtual
dispatch. Example:
 class A {
     ...
     virtual void foo() { ... } // inline
 };
 void g(A* p) { p->foo(); }
The compiler cannot know whether g will be passed some object
derived from A, so it must generate code for virtual dispatch
of function foo. Thus, foo must be generated out of line so
that its address is available.

In cases where the function is called in such a way that
virtual dispatch is not needed, as in
 Aobject.foo(); // not via pointer or reference
 p->A::foo(); // qualified name used
the compiler can generate the function inline.

Nothing prevents a function from being generated both inline and
out of line in the same program. A C++ implementation can on its
own decide to generate any function inline or out of line.

--
Steve Clamage, stephen.clamage@sun.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]