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.)
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?
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?
-- Garrett
Garrett D'Amore wrote:
> Stefan Teleman wrote:
>>
>>
>> Garrett D'Amore wrote:
>>> Thank you for your instructional description of the C++ language
>>> with respect to templates.
>>>
>>> There are a few significant points, that I think you keep missing,
>>> or are glossing over:
>>>
>>> When I said C++ doesn't separate *binary* interface from
>>> implementation, I was *not* talking about the nice separation done
>>> for the benefit of the programmer. I was talking about separation
>>> done across the boundary created by the linker ... AFAIK, C++ does
>>> not recognize that there is such an interface boundary.
>>>
>>> In C++, if an inline function is expanded by the compiler, but makes
>>> use of *private* members of the class, then the *binary
>>> implementation* of the resulting code is *tied* to the
>>> implementation, and if the implementation changes (e.g. by changing
>>> the dynamically linked library) then there can be unfortunate
>>> consequences.
>>>
>>> I'm not a template expert, so I'll demonstrate with a simple inline
>>> function using C++ circa 1990.
>>>
>>> class box {
>>> int width;
>>> int height;
>>> /* put more private details here... */
>>>
>>> public:
>>> void draw(); // private implementation elsewhere
>>>
>>> public inline int getwidth() { return width; }
>>> };
>>
>> This is a hypothetical example of a very poorly designed C++ class. I
>> would expect to see this type of design from a High School Student,
>> and not from a professional. Certainly not from an industry leader.
>>
>> The quality of this implementation aside, this code excerpt is not
>> from the Apache Standard C++ Library.
>>
>> Could you kindly provide an example of ABI breakage -- any kind of
>> breakage -- from the source code of the Apache Standard C++ Library,
>> currently under discussion ?
>>
>> Incidentally, the problem you are illustrating in your example has
>> been solved about 14 years ago (if not earlier):
>>
>> http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/ref=sr_1_1?ie=UTF8&s=books&qid=1220661045&sr=1-1
>>
>>
>>
>> Published November 10, 1994.
>>
>> As to which of the Design Patterns addresses this very exact problem
>> is left as an exercise for the reader.
>
> Okay, I'm not interested in debating this further ... or even
> researching it. I frankly don't have the energy to read the source
> code for a significant library written in a language I don't work in
> on a day to day basis.
>
> However, if you will assert that there are no binary compatibility
> problems of this nature (nor any others of a similar nature arising
> from templates) -- i.e. that the header files do not create a problem,
> then I don't have a problem.
>
> The litmus test for this problem would be to take an application
> compiled against one version the library, and replace the library
> underneath it with a different implementation. If the applications
> still work, then I'm satisfied. If the applications do not work, then
> we have to make some kind of continuity statements or guarantees about
> how we manage fixes and upgrades to the library. If Apache's
> implementation guarantees that this breakage doesn't occur on minor or
> patch upgrades, then that might be acceptable, although we have to
> figure out continuity to ensure that the library (or a drop in
> compatible replacement) will remain available for quite some time.
> (Standard commitment effectively means ~forever, btw.)
>
> That still doesn't address the other major set of concerns I had,
> about mixing and matching different implementations of the standard
> libraries. I think I'm unhappy with anything above Volatile
> commitment without a game plan that ultimately addresses the problem
> and gets us to a single "recommended" base library implementation.
>
> -- Garrett
>>
>> --Stefan
>>
>