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
>>
>


Reply via email to