You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by Farid Zaripov <Fa...@epam.com> on 2007/11/23 17:48:04 UTC

question on the examples for the source/forward/backward incompatible changes

  Whether these examples should be abstract, or based on C++ Standard
Library
declarations/definitions?

  Since the source  incompatible changes involves changes in
function/class mebmers
prototype, or changes in global data/class data members declaration, or
changing the
place of the some declaration (i.e. moving the declaration from one
header file to the another),
but requirements of the all of this are stated in C++ Standard and,
accordingly, any of these
changes are impossible.

Farid.

Re: question on the examples for the source/forward/backward incompatible changes

Posted by Martin Sebor <se...@roguewave.com>.
Farid Zaripov wrote:
>> -----Original Message-----
>> From: Martin Sebor [mailto:msebor@gmail.com] On Behalf Of Martin Sebor
>> Sent: Saturday, November 24, 2007 8:29 PM
>> To: stdcxx-dev@incubator.apache.org
>> Subject: Re: question on the examples for the 
>> source/forward/backward incompatible changes
>>
>> This is an interesting example because it doesn't actually 
>> break programs at compile time but rather changes their 
>> runtime behavior, something that typically is associated with 
>> binary compatibility.
> 
>   Why with binary compatibility?

Because changing the behavior of a function (or class) while
maintaining the same interface is usually considered a binary
incompatible change. E.g., changing the implementation of foo
from

     void* foo (int n) { return malloc (n * 2); }

to

     void* foo (int n) { return malloc (n); }

is a binary incompatible change. But simply adding an overload
for foo like this:

     void* foo (char) { return new char [256]; }

while binary compatible, is a source incompatible change. It
seemed like a subtle and interesting distinction to me :)

> From the current document:
> "Source compatibility also implies functional compatibility, although it
> does not necessarily imply binary compatibility."
> 
>   In this case if program already compiled this change is binary
> compatible, because the
> program don't knows about new overload of the existing function. At the
> same time this
> change is not source compatible because it's changes functionality of
> the program,
> compiled with the library with new overload function.

That's right.

Martin

> 
> 
>> Incidentally, we even have an enhancement request for this 
>> new inserter (maybe you've seen it):
>>      http://issues.apache.org/jira/browse/STDCXX-296
>>
>> But there certainly are cases where adding an overload can 
>> break programs by introducing an ambiguity where there 
>> previously was none.
>>
>> Martin


RE: question on the examples for the source/forward/backward incompatible changes

Posted by Farid Zaripov <Fa...@epam.com>.
> -----Original Message-----
> From: Martin Sebor [mailto:msebor@gmail.com] On Behalf Of Martin Sebor
> Sent: Saturday, November 24, 2007 8:29 PM
> To: stdcxx-dev@incubator.apache.org
> Subject: Re: question on the examples for the 
> source/forward/backward incompatible changes
> 
> This is an interesting example because it doesn't actually 
> break programs at compile time but rather changes their 
> runtime behavior, something that typically is associated with 
> binary compatibility.

  Why with binary compatibility? From the current document:
"Source compatibility also implies functional compatibility, although it
does not necessarily imply binary compatibility."

  In this case if program already compiled this change is binary
compatible, because the
program don't knows about new overload of the existing function. At the
same time this
change is not source compatible because it's changes functionality of
the program,
compiled with the library with new overload function.


> Incidentally, we even have an enhancement request for this 
> new inserter (maybe you've seen it):
>      http://issues.apache.org/jira/browse/STDCXX-296
> 
> But there certainly are cases where adding an overload can 
> break programs by introducing an ambiguity where there 
> previously was none.
> 
> Martin

Re: question on the examples for the source/forward/backward incompatible changes

Posted by Mark Brown <ma...@gmail.com>.
Martin Sebor wrote:
> Mark Brown wrote:
> [...]
>> Or adding overloads with different behavior to functions that are
>> a better match for calls in existing programs. For instance, if we
>> added an overload for the ostream inserter for wchar_t* that did
>> something different than print the value of the pointer it would
>> break programs that insert wchar_t pointers into narrow streams.
>> So code like this: std::cout << L"insert a pointer"; inserts the
>> address of the wide string today, but if we added the overload it
>> would write the string itself.
> 
> This is an interesting example because it doesn't actually break
> programs at compile time but rather changes their runtime behavior,
> something that typically is associated with binary compatibility.
> Incidentally, we even have an enhancement request for this new
> inserter (maybe you've seen it):
>     http://issues.apache.org/jira/browse/STDCXX-296
> 
> But there certainly are cases where adding an overload can break
> programs by introducing an ambiguity where there previously was
> none.

True. And even adding a new function can break source if its name
happens to be the same as the name of some user-defined function.
Namespaces are supposed to help prevent this but they cannot help
with member functions. For instance, adding the member function
data() to std::vector will break a class that derives from vector
and that calls a global function called data.

--Mark


Re: question on the examples for the source/forward/backward incompatible changes

Posted by Martin Sebor <se...@roguewave.com>.
Mark Brown wrote:
[...]
> Or adding overloads with different behavior to functions that are
> a better match for calls in existing programs. For instance, if we
> added an overload for the ostream inserter for wchar_t* that did
> something different than print the value of the pointer it would
> break programs that insert wchar_t pointers into narrow streams.
> So code like this: std::cout << L"insert a pointer"; inserts the
> address of the wide string today, but if we added the overload it
> would write the string itself.

This is an interesting example because it doesn't actually break
programs at compile time but rather changes their runtime behavior,
something that typically is associated with binary compatibility.
Incidentally, we even have an enhancement request for this new
inserter (maybe you've seen it):
     http://issues.apache.org/jira/browse/STDCXX-296

But there certainly are cases where adding an overload can break
programs by introducing an ambiguity where there previously was
none.

Martin

Re: question on the examples for the source/forward/backward incompatible changes

Posted by Mark Brown <ma...@gmail.com>.
Martin Sebor wrote:
> Farid Zaripov wrote:
>>   Whether these examples should be abstract, or based on C++ Standard
>> Library
>> declarations/definitions?
> 
> Examples using the C++ standard library classes or functions would
> be great, but any other sort will, in my opinion, work just as well.
> The point is to highlight the general kind of changes people might
> easily think are compatible when in reality they're not.
> 
>>
>>   Since the source  incompatible changes involves changes in
>> function/class mebmers
>> prototype, or changes in global data/class data members declaration, or
>> changing the
>> place of the some declaration (i.e. moving the declaration from one
>> header file to the another),
>> but requirements of the all of this are stated in C++ Standard and,
>> accordingly, any of these
>> changes are impossible.
> 
> Let me give one example where this isn't true. The standard leaves
> it up to each implementation to decide whether to define overloads
> of certain functions or whether to make use of default function
> arguments. For instance, vector::resize() can be declared in one
> of two ways:
> 
>     resize(size_type, value_type = value_type());
> 
> or
> 
>     resize(size_type);
>     resize(size_type, value_type);
> 
> Changing from one form to the other is detectable and might qualify
> as a breaking change. First, programs that explicitly instantiate
> vector on a user-defined type that's not default constructible will
> compile with the first declaration but not with the second (because
> the definition of the first overload must default-construct the
> element). Second, programs that take the address of such functions
> will not compile. The standard leaves the exact type of library
> member functions unspecified so it's up to us whether we want to
> go a step beyond and provide a stronger guarantee or not.

Or adding overloads with different behavior to functions that are
a better match for calls in existing programs. For instance, if we
added an overload for the ostream inserter for wchar_t* that did
something different than print the value of the pointer it would
break programs that insert wchar_t pointers into narrow streams.
So code like this: std::cout << L"insert a pointer"; inserts the
address of the wide string today, but if we added the overload it
would write the string itself.

--Mark

Re: question on the examples for the source/forward/backward incompatible changes

Posted by Martin Sebor <se...@roguewave.com>.
Farid Zaripov wrote:
>   Whether these examples should be abstract, or based on C++ Standard
> Library
> declarations/definitions?

Examples using the C++ standard library classes or functions would
be great, but any other sort will, in my opinion, work just as well.
The point is to highlight the general kind of changes people might
easily think are compatible when in reality they're not.

> 
>   Since the source  incompatible changes involves changes in
> function/class mebmers
> prototype, or changes in global data/class data members declaration, or
> changing the
> place of the some declaration (i.e. moving the declaration from one
> header file to the another),
> but requirements of the all of this are stated in C++ Standard and,
> accordingly, any of these
> changes are impossible.

Let me give one example where this isn't true. The standard leaves
it up to each implementation to decide whether to define overloads
of certain functions or whether to make use of default function
arguments. For instance, vector::resize() can be declared in one
of two ways:

     resize(size_type, value_type = value_type());

or

     resize(size_type);
     resize(size_type, value_type);

Changing from one form to the other is detectable and might qualify
as a breaking change. First, programs that explicitly instantiate
vector on a user-defined type that's not default constructible will
compile with the first declaration but not with the second (because
the definition of the first overload must default-construct the
element). Second, programs that take the address of such functions
will not compile. The standard leaves the exact type of library
member functions unspecified so it's up to us whether we want to
go a step beyond and provide a stronger guarantee or not.

Martin

Re: question on the examples for the source/forward/backward incompatible changes

Posted by Mark Brown <ma...@gmail.com>.
Farid Zaripov wrote:
>   Whether these examples should be abstract, or based on C++ Standard
> Library
> declarations/definitions?
> 
>   Since the source  incompatible changes involves changes in
> function/class mebmers
> prototype, or changes in global data/class data members declaration, or
> changing the
> place of the some declaration (i.e. moving the declaration from one
> header file to the another),
> but requirements of the all of this are stated in C++ Standard and,
> accordingly, any of these
> changes are impossible.

Hi Farid,

I believe the standard leaves some details unspecified so library
writers can decide how to implement them. For instance, default
arguments and overloads.

--Mark

> 
> Farid.
>