Topic: No more forward reference limitations
Author: abarbati@iaanus.com (Alberto Barbati)
Date: Wed, 22 Jan 2003 07:03:40 +0000 (UTC) Raw View
Richard J Cox wrote:
> Isn't exactly that kind of thing allowed anyway in certain contexts? After
> all this is valid...
>
>
> class X {
> void func(const std::string& s);
>
> void one()
> {
> func("foobar");
> }
>
> void func(const char* s);
> }
>
>
> (And this extends to referencing member variables that are declared after
> the inline member function definition.)
The objection is correct and interesting. Let me complicate a bit your
example, stripping off "class X" and using two compilation units:
>>>>>>>>> file a.h
inline void foo(const std::string& s) // #1
{
// ...
}
inline void bar(const char* s)
{
foo(s);
}
>>>>>>>>> file a.cpp
#include "a.h"
void test1()
{
bar("hello, world\n"); // invokes foo #1 eventually
}
>>>>>>>>> file b.cpp
#include "a.h"
void foo(const char* s) // #2
{
bar(s);
}
void test2()
{
bar("hello, world\n"); // invokes foo #2 eventually
}
>>>>>>>>> end example
You have commited the worst sin in C++, you have violated ODR.
The program would have two different implementation of function bar.
Remember that the keyword inline is just a hint, the compiler is not
required to honor it and if it chooses not to, the linker would have
hard trouble to decide which implementation to choose.
Indeed a class scope behaves differently from a namespace scope. This
example shows, IMHO, a good reason for that and to keep it at that. The
key fact is that a class scope is closed, while a namespace scope is
not. This means, in particular, that a compilation unit knows either all
declarations in a class scope or none of them. Namespace scopes do not
have this property and thus cannot be given certain "benefits".
Alberto Barbati
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: K.Hagan@thermoteknix.co.uk ("Ken Hagan")
Date: Mon, 20 Jan 2003 12:02:04 +0000 (UTC) Raw View
> News Admin wrote:
No s/he didn't. I wrote it. Either my company's proxy or my ISP
have stripped me of my identity. (K.Hagan@thermoteknix.co.uk)
"John Nagle" <nagle@animats.com> wrote...
>
> That would be a horribly ugly way to specify this feature.
> Declaration/call matching has to be independent of the
> order of declarations in the compilation unit.
>
> This implies deferring the final binding of call to
> declaration until the entire compilation unit has been
> parsed. An extra compiler pass might be required for
> some compilers, depending upon how much work they do
> in the first pass.
That's my point. Assuming that binding considers the *complete*
set of declarations, in an order-independent manner, anyone
writing inline functions in a header that make "less-than-exact"
references to other functions might suffer a change of meaning
depending on the later contents of the CPP file.
If the same header is included in another translation unit,
which doesn't provide the better match, we violate the ODR.
(Whose fault is that?)
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: rjcox@cix-remove-me-.co.uk (Richard J Cox)
Date: Mon, 20 Jan 2003 18:33:11 +0000 (UTC) Raw View
In article <3e25e9c9_1@corp.newsgroups.com>, abarbati@iaanus.com (Alberto
Barbati) wrote:
> David Spector wrote:
> > There is almost no implementation impact on compilers (it just
> > requires an
> > additional partial (fixup) pass at most, and such fixup already
> > occurs in
> > some contexts, such as in class declaration/definitions).
>
> It's not that simple, because of overloading. Consider this code:
>
> ---
> void func(const std::string& s) // #1
> {
> // [...]
> }
>
> int main()
> {
> func("foobar");
> }
>
> void func(const char* s) // #2
> {
> // [...]
> }
> ---
>
[...]
>
> Now, image that we accept you suggestion and we require the compiler to
> take also func #2 into consideration. As #2 is a better match than #1,
> it would choose the latter, but it can't simply change a fix-up! It
> needs to re-compile main from scratch, as the temporary is now no
> longer needed.
>
> This example is simple, but it can be complicated at will. We could
> have func #2 in adifferent compilation unit, for instance. Or we can
> imagine a pervert situation like this one:
>
Isn't exactly that kind of thing allowed anyway in certain contexts? After
all this is valid...
class X {
void func(const std::string& s);
void one()
{
func("foobar");
}
void func(const char* s);
}
(And this extends to referencing member variables that are declared after
the inline member function definition.)
--
rjcox at cix dot co dot uk
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: news@news.demon.net ("News Admin")
Date: Fri, 17 Jan 2003 17:04:40 +0000 (UTC) Raw View
"John Nagle" <nagle@animats.com>...
>
> It's non-trivial. With overloading, all less-than-perfect
> matches (ones that require promotions) have to be deferred, in case
> a better match shows up further along in the compilation unit.
> Nevertheless, it's possible. Given current compiler designs,
> how hard is it?
Doesn't this allow one to change the meaning of a block of code?
Imagine that function A calls a function B() with a less than
perfect match to arguments. Imagine that both of these are inline
in some header. Now if a client defines B1() which is a slightly
better match, we change A.
The author of A can defend against this by explicitly casting all
function arguments to the exact types expected by B. Then again,
if the feature were added, then I would expect compilers to warn
whenever forward references weren't exact matches. Thus, the
impact would be mainly felt by people with lots of old code that
they'd have to patch up "to be on the safe side".
Still, I can live with declaring functions in advance, and if your
proposal for private members sees the light of day then I can't
see that the incremental benefit of the OP's suggestion would be
worth the hassle.
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Fri, 17 Jan 2003 19:29:12 +0000 (UTC) Raw View
News Admin wrote:
> "John Nagle" <nagle@animats.com>...
>
>> It's non-trivial. With overloading, all less-than-perfect
>>matches (ones that require promotions) have to be deferred, in case
>>a better match shows up further along in the compilation unit.
>>Nevertheless, it's possible. Given current compiler designs,
>>how hard is it?
>>
>
> Doesn't this allow one to change the meaning of a block of code?
>
> Imagine that function A calls a function B() with a less than
> perfect match to arguments. Imagine that both of these are inline
> in some header. Now if a client defines B1() which is a slightly
> better match, we change A.
>
> The author of A can defend against this by explicitly casting all
> function arguments to the exact types expected by B. Then again,
> if the feature were added, then I would expect compilers to warn
> whenever forward references weren't exact matches.
That would be a horribly ugly way to specify this feature.
Declaration/call matching has to be independent of the
order of declarations in the compilation unit.
This implies deferring the final binding of call to
declaration until the entire compilation unit has been
parsed. An extra compiler pass might be required for
some compilers, depending upon how much work they do
in the first pass.
John Nagle
Animats
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ai@springtimesoftware.com ("David Spector")
Date: Wed, 15 Jan 2003 20:45:22 +0000 (UTC) Raw View
(this may be a re-post, but something may have gone wrong in the posting
process; I have seen no responses)
------
I wonder why, in these modern times, do we still have the 'no forward
reference' limitation? This sets C++ apart from most other programming
languages and makes programs harder to write and/or less natural to read, in
various situations.
There is almost no implementation impact on compilers (it just requires an
additional partial (fixup) pass at most, and such fixup already occurs in
some contexts, such as in class declaration/definitions).
There would apparently be no compatibility problem, since relaxing this
restriction should not make any existing programs fail to compile.
David Spector
President, Springtime Software
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: abarbati@iaanus.com (Alberto Barbati)
Date: Thu, 16 Jan 2003 03:46:10 +0000 (UTC) Raw View
David Spector wrote:
> There is almost no implementation impact on compilers (it just requires an
> additional partial (fixup) pass at most, and such fixup already occurs in
> some contexts, such as in class declaration/definitions).
It's not that simple, because of overloading. Consider this code:
---
void func(const std::string& s) // #1
{
// [...]
}
int main()
{
func("foobar");
}
void func(const char* s) // #2
{
// [...]
}
---
With the current standard, the statement in main is expanded as a call
to func #1, which is the only one available in scope. The compiled code,
however, is quite complex, as before calling func we have to construct a
temporary variable of type std::string, and after the call such
temporary must be destroyed.
Now, image that we accept you suggestion and we require the compiler to
take also func #2 into consideration. As #2 is a better match than #1,
it would choose the latter, but it can't simply change a fix-up! It
needs to re-compile main from scratch, as the temporary is now no longer
needed.
This example is simple, but it can be complicated at will. We could have
func #2 in adifferent compilation unit, for instance. Or we can imagine
a pervert situation like this one:
---
void foo(const std::string& s) // #1
{
// ...
}
void bar(const char* s)
{
foo(s);
}
void foo(const char* s) // #2
{
bar(s);
}
---
This code is ugly but valid C++. Calling either bar or foo #2 results in
calling foo #1 eventually. With your suggestion, this code creates a
endless loop between bar and foo #2 that will probably result in a stack
overflow.
> There would apparently be no compatibility problem, since relaxing this
> restriction should not make any existing programs fail to compile.
Failing to compile is not the problem. The examples above clearly show
that existing programs might change their runtime behaviour if such a
feature was introduced, possibly with undesired results. The probability
of such event is unknown to me, but certainly it is higher than 0 and
even such a small probability is unacceptable.
Alberto Barbati
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 16 Jan 2003 05:37:01 +0000 (UTC) Raw View
In article <v2bhtldtpbk637@corp.supernews.com>, David Spector
<ai@springtimesoftware.com> writes
>I wonder why, in these modern times, do we still have the 'no forward
>reference' limitation? This sets C++ apart from most other programming
>languages and makes programs harder to write and/or less natural to read, in
>various situations.
Please give an example of what you mean and how declarations do not meet
your need.
--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: nagle@animats.com (John Nagle)
Date: Fri, 17 Jan 2003 00:22:29 +0000 (UTC) Raw View
David Spector wrote:
> I wonder why, in these modern times, do we still have the 'no forward
> reference' limitation? This sets C++ apart from most other programming
> languages and makes programs harder to write and/or less natural to read, in
> various situations.
>
> There is almost no implementation impact on compilers (it just requires an
> additional partial (fixup) pass at most, and such fixup already occurs in
> some contexts, such as in class declaration/definitions).
>
> There would apparently be no compatibility problem, since relaxing this
> restriction should not make any existing programs fail to compile.
It's non-trivial. With overloading, all less-than-perfect
matches (ones that require promotions) have to be deferred, in case
a better match shows up further along in the compilation unit.
Nevertheless, it's possible. Given current compiler designs,
how hard is it?
I'd suggest allowing forward references to both static functions,
and to private member functions not declared in class declarations.
The latter, which have been discussed here previously, are a lot
like static functions from an implementation perspective.
John Nagle
Animats
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]