Topic: Compile-time construction?


Author: James.Kanze@dresdner-bank.com
Date: Wed, 13 Dec 2000 16:27:23 GMT
Raw View
In article <913igl$17d$1@nnrp1.deja.com>,
  Roger Orr <roger_orr@my-deja.com> wrote:
> In article <90l4fh$tj8$1@nnrp1.deja.com>,
>   James.Kanze@dresdner-bank.com wrote:
> > In article <90jd7k$h1u$1@nnrp1.deja.com>,
> >   Roger Orr <roger_orr@my-deja.com> wrote:

> > > > BTW, are compilers allowed to optimize the first call to make
> > > > it like second one? Or are they obliged to destroy the
> > > > temporary string right after call?

> > > They have to destroy the temporary -- unless (IIRC) ctor and
> > > dtor are inline and have 'no effect'.

> > They have to ensure that the program has the same observable
> > behavior as if they destroyed the temporary at the end of the full
> > expression.  Typically, to be sure that the observable behavior is
> > unchanged, they need access to the constructor and destructor,
> > which in turn typically (but not always!) implies inline.

> Thanks - that's rather better put than my answer!

> > The case of std::string, however, is different, because the
> > semantic of the constructor and destructor are completely defined
> > by the standard.

> I'm not sure about this...the _postconditions_ are specified (eg
> 21.3.1p2) but I didn't realise that necessarily meant the same
> as 'observable behavior'.

It's not.  Observable behavior is accessing a volatile variable, and
the calls to library IO routines.  And nothing else.

The postconditions specify the behavior of the abstract machine.  All
that is required is that for a legal program, the implementation give
the same results as if the behavior of the abstract machine had been
followed.  In the case of std::string, the compiler knows, or can
know, enough of the semantics to determine that the suppression of the
constructor and destructor have no effect on the observable behavior.
A library function cannot have additional side effects to those
specified in the standard.  None of the specified side effects in the
constructor or destructor of std::string are observable behavior, so
the implementation is pretty much free to do with them whatever it
wants.  As long as the resulting output is correct.

> [snip]
> >  Since they are part of the implementation,
> > in fact, the compiler is free to know what the results of the
> > constructor would be

> Does the standard imply you cannot 'plug in' another implementation
> of the standard library ?

The standard defines a complete language, including the library.  It
specifies what an implementation has to do to be conform.  (It also
leaves a lot up to the implementation: how to invoke the compiler,
linker, etc.)  It does not separate the language into two totally
independant parts, and it does not require an implementation to work
with parts of other implementations.  Most "implementations" in fact
do work with outside parts, like the operating system, etc.  They are
free to do so.  They are not required to do so.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com
http://www.deja.com/

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Roger Orr <roger_orr@my-deja.com>
Date: Thu, 14 Dec 2000 14:08:08 GMT
Raw View
In article <918654$nkn$1@nnrp1.deja.com>,
  James.Kanze@dresdner-bank.com wrote:
>
> It's not.  Observable behavior is accessing a volatile variable, and
> the calls to library IO routines.  And nothing else.
>
OK, and I've now found 17.3.1.3p3:-
"Postconditions: the observable results established by the function"

Presumably this means that a 'debugging' version of std::string which,
for example, writes statistics to a log file, is non-compliant.

As far as I can tell a 'diagnostic' version of a standard library
function which writes errors when for example, invalidated iterators
are used, _is_ compliant because the standard explicitly states failure
to comply with pre-conditions causes undefined behaviour!

Does is also mean that if I write a reference-counted std::string and
use a volatile variable as part of my implementatation of reference
counting this too is non-compliant?

--
Roger Orr. MVP in C++ for Brainbench at http://www.brainbench.com


Sent via Deja.com
http://www.deja.com/

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James.Kanze@dresdner-bank.com
Date: Thu, 14 Dec 2000 16:40:18 GMT
Raw View
In article <91a4jk$cbf$1@nnrp1.deja.com>,
  Roger Orr <roger_orr@my-deja.com> wrote:
> In article <918654$nkn$1@nnrp1.deja.com>,
>   James.Kanze@dresdner-bank.com wrote:

> > It's not.  Observable behavior is accessing a volatile variable,
> > and the calls to library IO routines.  And nothing else.

> OK, and I've now found 17.3.1.3p3:-
> "Postconditions: the observable results established by the function"

> Presumably this means that a 'debugging' version of std::string
> which, for example, writes statistics to a log file, is
> non-compliant.

I'd say no, it's not compliant.  But most implementations are only
fully compliant for a specific set of compiler options.  For example,
if I compile and link a program with the -p option, it writes
profiling data to disk.  I'd say that formally, this is not compilant,
since the functions I call do more than the standard specifies.  On
the other hand, does it really matter.  The code otherwise does
exactly what it does when compiled in compliant mode.  I'd rate this
in the same category as invoking the compiler in Posix mode -- the
compiler is definitely not compliant, but the differences are
documented, limited, and above all, don't affect the program (or at
least most programs) except when you want them to.

> As far as I can tell a 'diagnostic' version of a standard library
> function which writes errors when for example, invalidated iterators
> are used, _is_ compliant because the standard explicitly states
> failure to comply with pre-conditions causes undefined behaviour!

Right.  Once undefined behavior occurs, the compiler is automatically
compliant for that program, regardless of what it does.

> Does is also mean that if I write a reference-counted std::string
> and use a volatile variable as part of my implementatation of
> reference counting this too is non-compliant?

I would say no.  Although this is very tenuous, I would argue that
there is nothing you can do in a conformant program which can tell
that it uses a volatile variable.  After all, the implementation could
also write std::string in assembler, and there wouldn't be any issue
of compliance or not.  Even if the assembler corresponded exactly to
what the compiler would generate with the volatile variable.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com
http://www.deja.com/

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Roger Orr <roger_orr@my-deja.com>
Date: Tue, 12 Dec 2000 14:46:04 GMT
Raw View
In article <90l4fh$tj8$1@nnrp1.deja.com>,
  James.Kanze@dresdner-bank.com wrote:
> In article <90jd7k$h1u$1@nnrp1.deja.com>,
>   Roger Orr <roger_orr@my-deja.com> wrote:
>
> > > BTW, are compilers allowed to optimize the first call to make it
> > > like second one? Or are they obliged to destroy the temporary
> > > string right after call?
>
> > They have to destroy the temporary -- unless (IIRC) ctor and dtor
> > are inline and have 'no effect'.
>
> They have to ensure that the program has the same observable behavior
> as if they destroyed the temporary at the end of the full expression.
> Typically, to be sure that the observable behavior is unchanged, they
> need access to the constructor and destructor, which in turn typically
> (but not always!) implies inline.

Thanks - that's rather better put than my answer!

> The case of std::string, however,
> is different, because the semantic of the constructor and destructor
> are completely defined by the standard.

I'm not sure about this...the _postconditions_ are specified (eg
21.3.1p2) but I didn't realise that necessarily meant the same
as 'observable behavior'.

[snip]
>  Since they are part of the implementation,
> in fact, the compiler is free to know what the results of the
> constructor would be

Does the standard imply you cannot 'plug in' another implementation of
the standard library ?

Any references to the relevant bits of the standard appreciated - I
don't know my way around it well enough yet...

--
Roger Orr. MVP in C++ for Brainbench at http://www.brainbench.com


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: James.Kanze@dresdner-bank.com
Date: 2000/12/06
Raw View
In article <90jd7k$h1u$1@nnrp1.deja.com>,
  Roger Orr <roger_orr@my-deja.com> wrote:

> > BTW, are compilers allowed to optimize the first call to make it
> > like second one? Or are they obliged to destroy the temporary
> > string right after call?

> They have to destroy the temporary -- unless (IIRC) ctor and dtor
> are inline and have 'no effect'.

They have to ensure that the program has the same observable behavior
as if they destroyed the temporary at the end of the full expression.
Typically, to be sure that the observable behavior is unchanged, they
need access to the constructor and destructor, which in turn typically
(but not always!) implies inline.  The case of std::string, however,
is different, because the semantic of the constructor and destructor
are completely defined by the standard.  The compiler can thus know
them without looking at a single line of code.  And since they don't
have any side effects, the compiler is free to rearrange the code
taking advantage of this.  Since they are part of the implementation,
in fact, the compiler is free to know what the results of the
constructor would be, and simply lay the data down in static memory,
without even calling the constructor once.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Marco Manfredini" <marco@technoboredom.net>
Date: 2000/12/06
Raw View
"Andy Salnikov" <A.A.Salnikov@inp.nsk.su> wrote in message
news:90inum$2ui1f$1@sky.inp.nsk.su...
> huge overhead for the construction of std::string. After some
contemplation
> I said to myself "Why these damn strings cannot be constructed once
and for
> all, during compilation?" You know the answer, they just can't. Of
course we
> have to rewrite the above code, probably like this:

No reason for compile-time construction yet!.

Besides overloading your call with a "const char *" version, think about
a "stringref" class:

class stringref
{
 string hold;
 const char *ptr;
public:
 stringref(const char *p) : ptr(p) {} // hold remains empty, no overhead
& allocation here.
 stringref(const string &s) : hold(s) { ptr=hold.c_str(); } // copy, in
case "s" changes later
 operator string () { return string(ptr); }
 operator const char *() { return ptr; }
};

string str="xyz";

void foo(stringref x) // only this overload needed.
{
    // x works as a const char * here.
    str="123"; // foo(str) copied str internally, so you are safe here.
}

int main()
{
 foo("Hi"); // converts to a stringref which simply holds the pointer
 foo(str);  // copys the s.
}

--
Marco


---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Andy Salnikov" <A.A.Salnikov@inp.nsk.su>
Date: 2000/12/06
Raw View
"Roger Orr" <roger_orr@my-deja.com> wrote in message
news:90jd7k$h1u$1@nnrp1.deja.com...
> In article <90inum$2ui1f$1@sky.inp.nsk.su>,
>   "Andy Salnikov" <A.A.Salnikov@inp.nsk.su> wrote:
>
> > After some contemplation
> > I said to myself "Why these damn strings cannot be constructed once
> and for
> > all, during compilation?"
>
> You must be thinking of Java :)
>
  Probably, although I do not know much Java. What I'm thinking about
(sometimes) is that the string literals better had type of std::string.

> > You know the answer, they just can't. Of course we
> > have to rewrite the above code, probably like this:
> >
> Well, in C++ if performance is a problem you can always provide a
> overload that actually takes "const char *" as argument - provided
> you can then do a lookup on const char * in your data structures.
>
  I would agree with this, you only need to replace "always" with
"sometimes". There is plenty of code over which we have no control at all,
or too cautious to change anything in the working stuff.

  Cheers,
  Andy.


---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: James.Kanze@dresdner-bank.com
Date: 2000/12/06
Raw View
In article <90inum$2ui1f$1@sky.inp.nsk.su>,
  "Andy Salnikov" <A.A.Salnikov@inp.nsk.su> wrote:

>   am I the the only one dreaming this crazy dream? Let me explain
> what it is. Some time ago when doing some performance tuning for the
> working system I understood what I'd like to be in C++ -
> compile-time construction of the objects. That code had some methods
> which take a reference to std::string as parameter:

>   someType someMethod( const std::string& arg ) ;

> This method was called from zillions of places with the C-style
> strings:

>   value = someMetod( "thisIsWhatINeed" ) ;

> The method itself is supposed to be extremely fast, this is just a
> lookup in the associative array. Users of the method (they are not
> all C++ experts) seem do not realize that the above call, which
> looks very neat, brings a huge overhead for the construction of
> std::string. After some contemplation I said to myself "Why these
> damn strings cannot be constructed once and for all, during
> compilation?"

They can.  I don't know of any compiler that does so just yet, but the
standard certainly allows it.  Once compilers get all of the required
features in, I would expect that they will attact this sort of
problem.  (At present, most library implementations are from third
parties, and aren't particularly well integrated into the compiler.)

> You know the answer, they just can't. Of course we
> have to rewrite the above code, probably like this:

>   static const std::string argThisIsWhatINeed("thisIsWhatINeed") ;
>   value = someMetod( argThisIsWhatINeed ) ;

> but it does not add anything to the clarity of the above expression,
> and it's not as good as compile-time constructor :) Could it be then
> that some day I see the latter in reality?

If there is a demand, you will see it.

> Or is it so bad that
> it'll become a nightmare? BTW, are compilers allowed to optimize the
> first call to make it like second one? Or are they obliged to
> destroy the temporary string right after call?

Both:-).  The lifetime of the temporary string ends at the end of the
full expression.  But since there is no way for a conforming program
to tell, the compiler is free to make the optimization you suggest.
Still, as the compilers become more library-aware, I would expect them
to just lay out the necessary data structures in memory, without even
calling the constructor once.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                  Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Andy Salnikov" <A.A.Salnikov@inp.nsk.su>
Date: 2000/12/05
Raw View
  Hi all,

  am I the the only one dreaming this crazy dream? Let me explain what it
is. Some time ago when doing some performance tuning for the working system
I understood what I'd like to be in C++ - compile-time construction of the
objects. That code had some methods which take a reference to std::string as
parameter:

  someType someMethod( const std::string& arg ) ;

This method was called from zillions of places with the C-style strings:

  value = someMetod( "thisIsWhatINeed" ) ;

The method itself is supposed to be extremely fast, this is just a lookup in
the associative array. Users of the method (they are not all C++ experts)
seem do not realize that the above call, which looks very neat, brings a
huge overhead for the construction of std::string. After some contemplation
I said to myself "Why these damn strings cannot be constructed once and for
all, during compilation?" You know the answer, they just can't. Of course we
have to rewrite the above code, probably like this:

  static const std::string argThisIsWhatINeed("thisIsWhatINeed") ;
  value = someMetod( argThisIsWhatINeed ) ;

but it does not add anything to the clarity of the above expression, and
it's not as good as compile-time constructor :) Could it be then that some
day I see the latter in reality? Or is it so bad that it'll become a
nightmare? BTW, are compilers allowed to optimize the first call to make it
like second one? Or are they obliged to destroy the temporary string right
after call?

  Cheers,
  Andy.

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: Roger Orr <roger_orr@my-deja.com>
Date: 2000/12/05
Raw View
In article <90inum$2ui1f$1@sky.inp.nsk.su>,
  "Andy Salnikov" <A.A.Salnikov@inp.nsk.su> wrote:
>   Hi all,
>
[snip]
>   someType someMethod( const std::string& arg ) ;
>
> This method was called from zillions of places with the C-style
strings:
>
>   value = someMetod( "thisIsWhatINeed" ) ;
>
[snip]
> After some contemplation
> I said to myself "Why these damn strings cannot be constructed once
and for
> all, during compilation?"

You must be thinking of Java :)

> You know the answer, they just can't. Of course we
> have to rewrite the above code, probably like this:
>
Well, in C++ if performance is a problem you can always provide a
overload that actually takes "const char *" as argument - provided
you can then do a lookup on const char * in your data structures.

[snip]

> BTW, are compilers allowed to optimize the first call to make it
> like second one? Or are they obliged to destroy the temporary string
right
> after call?

They have to destroy the temporary -- unless (IIRC) ctor and dtor are
inline and have 'no effect'.

--
Roger Orr. MVP in C++ for Brainbench at http://www.brainbench.com


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]