Garrett D'Amore wrote: > Reading the Apache C++ sources (which I didn't want to do, but here you > go), I ran into the following example snippet in the include directory > (the include file is <streambuf>): > > template<class _CharT, class _Traits> > inline typename basic_streambuf<_CharT, _Traits>::int_type > basic_streambuf<_CharT, _Traits>:: > sputbackc (char_type __c) > { > _RWSTD_ASSERT (_C_is_valid ()); > > if (_C_putback_avail () && traits_type::eq (*(gptr () - 1), __c)) > return traits_type::to_int_type (*--_C_gptr); > > return pbackfail (traits_type::to_int_type (__c)); > } > > > In the above example, the inline function has in it bits which appear to > me to be implementation details (_C_putback_avail() is protected for > example -- I'm not sure whether the *standard* specifies that it exist > or not. _C_gptr is certainly a private member of the class, and I > "presume" that the standard doesn't specify it, though I've not checked > the standard since I don't have a copy of it handy.) > > The concern here is what happens if those portions of the implementation > need to change? (What happens if _C_gptr moves in the class, or the > implementation needs to change in a way that _C_gptr doesn't exist at > all, or changes type? Bad things, I suspect.)
These changes cannot be made. Not for the duration of Major Release 4. This is what the Standard says about this particular member function: 27.5.2.2.4 Putback int_type sputbackc(char_type c); 1 Returns: If the input sequence putback position is not available, or if traits::eq(c, gptr()[-1]) is false, returns pbackfail(traits::to_int_type(c)). Otherwise, decrements the next pointer for the input sequence and returns traits::to_int_type (*gptr()). The function _C_putback_avail() is private to this implementation of the Library (in the Apache Library's case all functions, or data members whose names begin with "_C" are private to the implementation). The pointer _C_gptr (or a functional equivalent thereof) is mandated by the Standard. This naming convention is a warning to the developer of the application consuming the interfaces exposed by <streambuf>: Do Not Use These Functions Directly Under Any Circumstances Whatsoever. Also, the fact that is is protected imposes restrictions on access. The important aspect is that the gptr() (which Apache calls _C_gptr) is explicitly mentioned in the Standard. If you compare version 4.2.1 of this Standard header file with the same header file from versions 4.2.0, or 4.1.3, you will see that the changes made to this header file do not break binary compatibility. > Will the implementation take care to preserve the *existing* functions > so that the above inline (which will now have been compiled into various > applications) will continue to function, regardless of what other > changes may be necessary for the class? The implementation *must* preserve those functions and data members (or functional equivalents thereof) which are mandated by the Standard. These cannot be changed in any way -- they are immutable. New, non-virtual member functions could be added to this class (non-virtual functions do not affect the size or the layout of the object, or of the __vtbl), provided that their names begins with "_C", and are therefore labeled as private to the implementation. Static member functions could be safely added (they don't even have an implicit "this" pointer at all, and they do not affect the size or the layout of the object), subject to the same naming convention constraints. New virtual member functions, and/or new data members cannot be added, under any circumstances whatsoever. But such additions should not be even considered in the first place -- this version of the Standard is frozen. Adding a virtual function to this class will first and foremost violate the interfaces mandated by the Standard. What could change, with less restrictions, are the private implementation details which can be found in the $(top_srcdir)/src directory, and whose names begin with "__rw". > I apologize for my apparently childish C++ example earlier -- as I said, > I don't work in the language very often. But I *think* I've found a > real example from Apache C++ that suffers the same problem. Do you > disagree? I do not see this example as a reason for binary compatibility breakage concern, provided that the rules for preserving binary compatibility are observed (which I have no reason to believe that they will not be). Everything i've said here i can guarantee that is is also very well known by the Apache/RogueWave developers as well -- most likely much more. No apologies necessary. There are design circumstances in which the developer of the library interface simply knows that the class layout cannot change, ever. For those circumstances, freezing the object layout is appropriate. KDE, and QT, intentionally do not use this approach. For all the library classes which expose public interfaces available to external consumers, the private implementation details are hidden by means of the Bridge or Facade Design Patterns (pImpl pattern). The actual implementation of the header file only exposes member functions, and the only data member is an opaque pointer to the private implementation. The actual private implementation is done in the *.cpp translation unit. --Stefan -- Stefan Teleman Sun Microsystems, Inc. Stefan.Teleman at Sun.COM