Topic: A sketch of a proposal.
Author: yechezkel@emailaccount.com ("Yechezkel Mett")
Date: Thu, 7 Jul 2005 15:29:10 GMT Raw View
<kanze@gabi-soft.fr> wrote in message
news:1118824826.804389.175220@f14g2000cwb.googlegroups.com...
> Graeme Prentice wrote:
> > VC2003 (Dinkumware) has some infomation for containers and
> > iostreams thread safety but nothing specifically on the C
> > library. Since there are multi-threaded and single-threaded
> > versions of the C runtime the assumption is that everything
is
> > thread safe with the multithreaded libs!
>
> In practice, without garbage collection, it is impossible to
> implement a thread safe version of localtime. And a thread
safe
> version of strtok is a total contradiction.
I can't find the documentation now, but I have seen it in the
past - if you use Microsoft's multithreaded C runtime library all
the library functions are thread-safe, including localtime and
strtok. This is accomplished by allocating a separate memory
block for each thread for the runtime to use (I don't know if it
actually uses thread-local storage, but the effect is the same).
The same applies to strtok; just be aware that using it in one
thread has no effect on any other thread (in other words each
thread operates on a different token string).
This is certainly the most convenient way (for the user) to make
the library thread-safe -- it is totally transparent.
Yechezkel Mett
---
[ 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: yecril@bluebottle.com ("Krzysztof Zelechowski")
Date: Mon, 13 Jun 2005 16:01:51 GMT Raw View
Uzytkownik "Graeme Prentice" <gp.kiwi@gmail.com> napisal w wiadomosci
news:76vma15501k4dbf5sunt8q8lec2do9bro9@4ax.com...
> On Sat, 11 Jun 2005 21:42:53 GMT, "Krzysztof Zelechowski" wrote:
>
>>
>>I had a similar problem when I wanted to derive from struct tm and
>>construct
>>with a value of type time_t via localtime();
>>
>>I cannot MyTM(time_t t): tm(*localtime(t))
>>
>>because localtime(t) can be 0; I had to use another constructor MyTM(tm
>>*atm) that checks whether atm; and the solution is
>>
>>MyTM(time_t t): tm(MyTM(localtime(t))
>>
>>I personally think that it is clumsy and that there should be a better way
>>to allow conditional expressions with cached values in the initializer
>>list.
>>One could use a static member variable for that purpose but it is unsafe
>>when the application is multithreaded (apart from the fact that localtime
>>is
>>unsafe itself, but it could be replaced with a safe function of your
>>choice).
>
> Yeah, localtime, along with a few other C features, can't be called from
> multiple threads. (How do you find out the thread-safety of "C" library
> functions with GCC?)
I cannot use GCC because I write commercial software.
>
> Your solution looks like it might recurse forever.
A different constructor is called here so the recursion is not evident. And
indeed, there is none.
> What's wrong with a
> call to a simple inline function to check for the null pointer
>
> inline tm fix(tm*pmt) { if (pmt) return *pmt; else return tm(); }
>
> MyTM(time_t t): tm(fix(*localtime(t)))
>
There is nothing wrong with it but the method fix is semantically a
constructor, so why not express it as an overloaded constructor?
> Regarding caching, if you can't use a static variable and don't want to
> use synchronization or a non-static member variable (in a
> first-in-construction-order base class using Daphne Pfister's method),
> you can always add a dummy parameter to the constructor parameter list
> that is a reference to whatever kind of temporary (i.e. stack based)
> object you like - initialized with a default value.
>
That is a great idea, thanks for the hint.
Chris
---
[ 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: f.fracassi@gmx.net (Fabio Fracassi)
Date: Mon, 13 Jun 2005 17:26:59 GMT Raw View
===================================== MODERATOR'S COMMENT:
Please do not post followups unless they bring this
thread back on topic.
===================================== END OF MODERATOR'S COMMENT
Krzysztof Zelechowski wrote:
>
> Uzytkownik "Graeme Prentice" <gp.kiwi@gmail.com> napisal w wiadomosci
> news:76vma15501k4dbf5sunt8q8lec2do9bro9@4ax.com...
>> On Sat, 11 Jun 2005 21:42:53 GMT, "Krzysztof Zelechowski" wrote:
>>
[snip]
>> Yeah, localtime, along with a few other C features, can't be called from
>> multiple threads. (How do you find out the thread-safety of "C" library
>> functions with GCC?)
>
> I cannot use GCC because I write commercial software.
>
This statement is not correct! You can use GCC to develop commercial
software (even closed source).
(see http://gcc.gnu.org/onlinedocs/libstdc++/17_intro/license.html)
Fabio
---
[ 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: caj@cs.york.ac.uk (chris jefferson)
Date: Mon, 13 Jun 2005 23:55:51 GMT Raw View
===================================== MODERATOR'S COMMENT:
Let's try to stay within the charter of this newsgroup. Further discussion
about the commercial of GCC and its licensing (as opposed to
standard-confromance) belong in some other newsgroup.
===================================== END OF MODERATOR'S COMMENT
Krzysztof Zelechowski wrote:
>
> I cannot use GCC because I write commercial software.
>
I'm sure I won't be the only person to reply to this by any means, but
there is of course no reason at all you can't write commercial software
using GCC, and GCC places no requirements at all on how you distribute
programs and libraries compiled with it. The libraries supplied with GCC
(glibc for C, and libstdc++ for C++ in particular) have licences which
ensure you can link with them and write programs using them and also
distribute using any licence you like.
Chris
---
[ 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: kanze@gabi-soft.fr
Date: Tue, 14 Jun 2005 09:58:36 CST Raw View
Graeme Prentice wrote:
[...]
> Yeah, localtime, along with a few other C features, can't be
> called from multiple threads. (How do you find out the
> thread-safety of "C" library functions with GCC?)
You read the documentation. Unless some specific guarantees are
given, it's not thread safe:-).
Seriously, g++ is a special case here, because its C library
is normally provided by the platform -- for G++ under Solaris,
for example, the localtime function is actually provided by
Solaris (which in turn, refers to Posix, which says that it
cannot be used in a multithreaded environment).
For platforms where there is no local environment, there is a
libc project. Since it is also used as the "local environment"
for Linux, and Linux aims for Posix conformance with regards to
threading, I suppose that the Posix guarantees are also valid
here. But I'm not sure: the g++ documentation (referring more
to the C++ parts of the library, of course) is less than clear,
but the actual guarantees given are less than what Posix
normally requires.
But of course, I'm really just guessing. If you're looking for
written guarantees (which is really what one would like), I
don't think you'll find much. Neither for g++, nor for far too
many commercial compilers. This is the sort of thing which
really needs to be covered by the standard.
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ 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: gp.kiwi@gmail.com (Graeme Prentice)
Date: Wed, 15 Jun 2005 04:26:26 GMT Raw View
On Tue, 14 Jun 2005 09:58:36 CST, kanze@gabi-soft.fr wrote:
>Graeme Prentice wrote:
>
> [...]
>> Yeah, localtime, along with a few other C features, can't be
>> called from multiple threads. (How do you find out the
>> thread-safety of "C" library functions with GCC?)
>
>You read the documentation. Unless some specific guarantees are
>given, it's not thread safe:-).
>
>Seriously, g++ is a special case here, because its C library
>is normally provided by the platform -- for G++ under Solaris,
>for example, the localtime function is actually provided by
>Solaris (which in turn, refers to Posix, which says that it
>cannot be used in a multithreaded environment).
So for Windows/mingw that would be msvcrt?
>
>For platforms where there is no local environment, there is a
>libc project. Since it is also used as the "local environment"
>for Linux, and Linux aims for Posix conformance with regards to
>threading, I suppose that the Posix guarantees are also valid
>here. But I'm not sure: the g++ documentation (referring more
>to the C++ parts of the library, of course) is less than clear,
>but the actual guarantees given are less than what Posix
>normally requires.
Ok, that's what I was wondering. With GCC being used to build Linux and
Linux being "somewhat multithreaded" I would have thought there was a
"fair amount" of thread safety in functions like printf but I've never
been able to find any documentation that says so, nor for Borland or
Visual C++.
VC2003 (Dinkumware) has some infomation for containers and iostreams
thread safety but nothing specifically on the C library. Since there
are multi-threaded and single-threaded versions of the C runtime the
assumption is that everything is thread safe with the multithreaded
libs!
>
>But of course, I'm really just guessing. If you're looking for
>written guarantees (which is really what one would like), I
>don't think you'll find much. Neither for g++, nor for far too
>many commercial compilers. This is the sort of thing which
>really needs to be covered by the standard.
That would be nice. Is the C language making any moves towards
multithreading support or just C++?
Graeme
---
[ 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: kanze@gabi-soft.fr
Date: Wed, 15 Jun 2005 12:12:27 CST Raw View
Graeme Prentice wrote:
> On Tue, 14 Jun 2005 09:58:36 CST, kanze@gabi-soft.fr wrote:
> >Graeme Prentice wrote:
> > [...]
> >> Yeah, localtime, along with a few other C features, can't be
> >> called from multiple threads. (How do you find out the
> >> thread-safety of "C" library functions with GCC?)
> >You read the documentation. Unless some specific guarantees
> >are given, it's not thread safe:-).
> >Seriously, g++ is a special case here, because its C library
> >is normally provided by the platform -- for G++ under
> >Solaris, for example, the localtime function is actually
> >provided by Solaris (which in turn, refers to Posix, which
> >says that it cannot be used in a multithreaded environment).
> So for Windows/mingw that would be msvcrt?
I'm not sure. For a number of reasons, all commercial Unix
systems provide a bundled implementation of the standard C
library; this is what g++ uses. I don't know if something like
msvcrt is bundled with Windows, or not; if it isn't, then it is
probable that g++ uses the GNU implementation of libc there as
well. (The GNU libc is the "bundled" version for Linux, as
well. Except that I imagine that it has been hacked by the
Linux people, since Unix compatibility requires a lot of
functions there which aren't part of standard C.)
> >For platforms where there is no local environment, there is a
> >libc project. Since it is also used as the "local
> >environment" for Linux, and Linux aims for Posix conformance
> >with regards to threading, I suppose that the Posix
> >guarantees are also valid here. But I'm not sure: the g++
> >documentation (referring more to the C++ parts of the
> >library, of course) is less than clear, but the actual
> >guarantees given are less than what Posix normally requires.
> Ok, that's what I was wondering. With GCC being used to build
> Linux and Linux being "somewhat multithreaded"
Recent versions of Linux have full pthreads support, as far as I
know. That's more than "somewhat multithreaded".
> I would have thought there was a "fair amount" of thread
> safety in functions like printf but I've never been able to
> find any documentation that says so, nor for Borland or Visual
> C++.
Well, you won't find it in the standard, because neither C nor
C++ officially recognize threads. Formally, I would say that if
it isn't explicitly documented by the implemention, you should
suppose that the function isn't thread safe, in any way. And
that you need to protect and serialize all uses of it. (In
practice, of course, it is *probably* safe to assume that
e.g. memcpy is thread safe. But only probably.)
Formally, I would say that unless a compiler rigorously
documents all of its thread safety guarantees, it cannot be used
in a multi-threaded environment. But that's a bit hard: most
compilers don't, and we have to use them anyway. The result is
that, on a Posix machine, without further documentation, I
suppose Posix compliance for the C compatible subset of C++.
For other operations, it's somewhat more difficult to say: the
compilers I know do try to make exceptions thread safe, for
example (although I've never seen this fact documented), but
none of them seem to care about the initialization of local
static variables. In the end, it's more guesswork than anything
else. (And all of the critical applications I've worked on have
been single threaded, rather than to take the risk, or to fall
back to C, where we know what is guaranteed.)
> VC2003 (Dinkumware) has some infomation for containers and
> iostreams thread safety but nothing specifically on the C
> library. Since there are multi-threaded and single-threaded
> versions of the C runtime the assumption is that everything is
> thread safe with the multithreaded libs!
In practice, without garbage collection, it is impossible to
implement a thread safe version of localtime. And a thread safe
version of strtok is a total contradiction. For that matter, I
would be somewhat surprised if printf were "thread-safe", at
least in the most usual sense given to the word. (On the other
hand, I would expect to be able to call fprintf on two different
FILE*, from two different threads, without problems.) But who
knows?
> >But of course, I'm really just guessing. If you're looking
> >for written guarantees (which is really what one would like),
> >I don't think you'll find much. Neither for g++, nor for far
> >too many commercial compilers. This is the sort of thing
> >which really needs to be covered by the standard.
> That would be nice. Is the C language making any moves
> towards multithreading support or just C++?
I don't know. I don't follow C standardization at all any more.
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ 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: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Fri, 10 Jun 2005 14:01:57 GMT Raw View
Hello,
Recently in comp.lang.c++ (and several times before that in other
places) I've seen a request to call a function to do some work
at the moment of initialising a class, usually in the constructor
initialiser list. The request is something like
struct A {
A(); // some other processing
};
struct B : A {
B() : <<< do_something_here() >>> A() {}
};
where 'do_something_here' could be a member of 'B' or any other
function that might even be unrelated to B or A. The kludgy way
of solving this is to give 'A's constructor an argument and make
'do_something_here()' to return something. It's cheating, in my
opinion, besides, it's not always possible if 'A' is not my class.
Of course, wrappers are there for our enjoyment, but I thought of
another solution, which is not necessarily good, it would require
changes in the language, and that's why I'd like your opinion.
* * *
What if we allowed any function to be called where 'void' argument
is expected (just like we do in a statement that discards the
result of the function call)? Similar rules already work when
we want to return, we can say
void a_function_that_returns_void();
void bar() {
return a_function_that_returns_void();
}
So, why not allow
void foo(); // no arguments, 'void foo(void)' in C terms
void bar(int); // returns 'void', arguments don't matter here
void foobar() {
return foo(bar(42)); // expression of interest
}
In the last executable statement, 'bar(42)' is called, the side
effects take place, then 'foo' is called.
It probably solves no particular problem if you don't consider
constructor initialiser lists, however, if you do then this becomes
possible:
void do_something_here(int);
struct A {
A(); // some other processing
};
struct B : A {
B() : A(do_something_here(42)) {}
};
The side effects of 'do_something_here' take place before 'A' is
initialised, then 'A's constructor is invoked.
Have you heard of something like that before? If yes, do you have
some links to the relevant discussions? If not, what do you think?
I would extend the proposal to accommodate functions that _do_ return
non-void. When called as the argument to a function that takes 'void',
the return value is simply discarded just like we do here:
int main() {
int foo();
foo(); // the return value is not used anywhere.
}
Now, I've not thought this whole thing through completely yet, the main
area of possible conflict and where we'd need to find the solution is
the overload resolution in such case. If we have
int main() {
void foo();
void foo(int);
void bar();
foo(bar());
}
it by no means can call 'foo(int)' simply because 'bar's return value
is not 'int', and there is no 'int' to pass to 'foo(int)'. If we have
int main() {
void foo();
void foo(int);
int bar();
foo(bar());
}
then there is no problem, the behaviour should be like it is now. I
have to admit that not being an expert in overload resolution I cannot
foresee any other hidden problems. Please bring them up.
I would appreciate if someone more versed in legalese or standardese than
me could help me by writing up a proposal should this all look attractive.
Thank you.
Victor
---
[ 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@robinton.demon.co.uk (Francis Glassborow)
Date: Fri, 10 Jun 2005 16:51:49 GMT Raw View
In article <Irgqe.82265$NC6.55399@newsread1.mlpsca01.us.to.verio.net>,
Victor Bazarov <v.Abazarov@comAcast.net> writes
>Recently in comp.lang.c++ (and several times before that in other
>places) I've seen a request to call a function to do some work
>at the moment of initialising a class, usually in the constructor
>initialiser list. The request is something like
>
> struct A {
> A(); // some other processing
> };
>
> struct B : A {
> B() : <<< do_something_here() >>> A() {}
> };
>
>where 'do_something_here' could be a member of 'B' or any other
>function that might even be unrelated to B or A. The kludgy way
>of solving this is to give 'A's constructor an argument and make
>'do_something_here()' to return something. It's cheating, in my
>opinion, besides, it's not always possible if 'A' is not my class.
>
>Of course, wrappers are there for our enjoyment, but I thought of
>another solution, which is not necessarily good, it would require
>changes in the language, and that's why I'd like your opinion.
I think your suggested solution is too wide. What we might do (but we
have an awful lot of work involving initialisation already) is to allow
code such as the following to work:
#include <iostream>
#include <ostream>
void bar(){
std::cout << "done\n";
}
struct example{
int i_;
example(int i = 1): i_(bar(),i){}
};
int main(){
example x(2);
}
Actually, I am a little surprised that I cannot use the comma operator
in an initialisation expression.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ 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: "Daphne Pfister" <lanatha@gmail.com>
Date: Fri, 10 Jun 2005 11:59:18 CST Raw View
Victor Bazarov wrote:
> Recently in comp.lang.c++ (and several times before that in other
> places) I've seen a request to call a function to do some work
> at the moment of initialising a class, usually in the constructor
> initialiser list. The request is something like
>
>
> struct A {
> A(); // some other processing
> };
>
>
> struct B : A {
> B() : <<< do_something_here() >>> A() {}
> };
>
>
> where 'do_something_here' could be a member of 'B' or any other
> function that might even be unrelated to B or A. The kludgy way
> of solving this is to give 'A's constructor an argument and make
> 'do_something_here()' to return something. It's cheating, in my
> opinion, besides, it's not always possible if 'A' is not my class.
This can be done without changing A or wrapping A, by using a re-usable
helper class.
struct pre_init {
explicit pre_init(bool) {}
};
struct A {
A(); // some other processing
};
struct B : private pre_init, pubilc A {
B()
: pre_init((do_something_here()
,do_something_else()
,true))
, A()
{}
};
I think that if anything was changed with C++ to make this easy it
should just be a library change and not a language change. I could see
this generalized to something like this.
template <int N=0, typename T=bool>
struct in_place_init {
explicit in_place_init(T) {}
};
Where it could be used as follows
struct my_class
: private in_place_init<0>
, public base_class_a
, private in_place_init<1>
, public base_class_b
, private_in_place_init<2>
, public base_class_c
{
my_class();
void do_something_before_a();
void do_something_before_b();
void do_something_before_c();
}
my_class::my_class()
: in_place_init<0>((do_something_before_a(),true))
, base_class_a()
, in_place_init<1>((do_something_before_b(),true))
, base_class_b()
, in_place_init<2>((do_something_before_c(),true))
, base_class_c()
{
}
---
[ 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: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Fri, 10 Jun 2005 19:53:49 GMT Raw View
Francis Glassborow wrote:
> In article <Irgqe.82265$NC6.55399@newsread1.mlpsca01.us.to.verio.net>,
> Victor Bazarov <v.Abazarov@comAcast.net> writes
>
>>Recently in comp.lang.c++ (and several times before that in other
>>places) I've seen a request to call a function to do some work
>>at the moment of initialising a class, usually in the constructor
>>initialiser list. The request is something like
>>
>> struct A {
>> A(); // some other processing
>> };
>>
>> struct B : A {
>> B() : <<< do_something_here() >>> A() {}
>> };
>>
>>where 'do_something_here' could be a member of 'B' or any other
>>function that might even be unrelated to B or A. The kludgy way
>>of solving this is to give 'A's constructor an argument and make
>>'do_something_here()' to return something. It's cheating, in my
>>opinion, besides, it's not always possible if 'A' is not my class.
>>
>>Of course, wrappers are there for our enjoyment, but I thought of
>>another solution, which is not necessarily good, it would require
>>changes in the language, and that's why I'd like your opinion.
>
>
> I think your suggested solution is too wide. What we might do (but we
> have an awful lot of work involving initialisation already) is to allow
> code such as the following to work:
>
> #include <iostream>
> #include <ostream>
>
> void bar(){
> std::cout << "done\n";
> }
>
> struct example{
> int i_;
> example(int i = 1): i_(bar(),i){}
example(int i = 1) : i_((bar(),i)) {}
should do it, no?
> };
>
> int main(){
> example x(2);
> }
>
> Actually, I am a little surprised that I cannot use the comma operator
> in an initialisation expression.
You can, just need another set of parentheses.
V
---
[ 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: brok@rubikon.pl (Bronek Kozicki)
Date: Fri, 10 Jun 2005 21:04:18 GMT Raw View
Daphne Pfister wrote:
> This can be done without changing A or wrapping A, by using a re-usable
> helper class.
>
> struct pre_init {
> explicit pre_init(bool) {}
> };
>
> struct A {
> A(); // some other processing
> };
>
> struct B : private pre_init, pubilc A {
> B()
> : pre_init((do_something_here()
> ,do_something_else()
> ,true))
> , A()
> {}
> };
>
it looks like rather nasty workaround. Maybe while fixing initialization
some alternative, more elegant solution will come up. I think that
initialization syntax should be extended anyway (to allow initialization
of const array), maybe new syntax will provide enough space to do
something with this problem.
B.
---
[ 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: kon@iki.fi (Kalle Olavi Niemitalo)
Date: Sat, 11 Jun 2005 16:33:56 GMT Raw View
v.Abazarov@comAcast.net (Victor Bazarov) writes:
> struct B : A {
> B() : <<< do_something_here() >>> A() {}
> };
How about this syntax:
struct B : A {
B() : void(do_something_here()), A() {}
};
As B& is implicitly convertible to void&, this could almost be
considered initialization of a base object. (On the other hand,
void would have to be a virtual base to mesh with the semantics
of dynamic_cast, and then you have a problem if another class
derives from B, because only the constructor of the most derived
class gets to initialize virtual bases.)
---
[ 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: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Sat, 11 Jun 2005 21:41:56 GMT Raw View
Kalle Olavi Niemitalo wrote:
> v.Abazarov@comAcast.net (Victor Bazarov) writes:
>
>> struct B : A {
>> B() : <<< do_something_here() >>> A() {}
>> };
>
> How about this syntax:
>
> struct B : A {
> B() : void(do_something_here()), A() {}
> };
>
> As B& is implicitly convertible to void&,
I somehow think there is no such thing as 'void&'... Is there?
> [...]
V
---
[ 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: yecril@bluebottle.com ("Krzysztof Zelechowski")
Date: Sat, 11 Jun 2005 21:42:53 GMT Raw View
Uzytkownik "Victor Bazarov" <v.Abazarov@comAcast.net> napisal w wiadomosci
news:Irgqe.82265$NC6.55399@newsread1.mlpsca01.us.to.verio.net...
> Hello,
>
> Recently in comp.lang.c++ (and several times before that in other
> places) I've seen a request to call a function to do some work
> at the moment of initialising a class, usually in the constructor
> initialiser list. The request is something like
>
> struct A {
> A(); // some other processing
> };
>
> struct B : A {
> B() : <<< do_something_here() >>> A() {}
> };
>
> where 'do_something_here' could be a member of 'B' or any other
Cannot, because B has not been constructed. You cannot call member
functions of objects that have not been constructed yet.
> function that might even be unrelated to B or A. The kludgy way
> of solving this is to give 'A's constructor an argument and make
> 'do_something_here()' to return something. It's cheating, in my
> opinion, besides, it's not always possible if 'A' is not my class.
>
I had a similar problem when I wanted to derive from struct tm and construct
with a value of type time_t via localtime();
I cannot MyTM(time_t t): tm(*localtime(t))
because localtime(t) can be 0; I had to use another constructor MyTM(tm
*atm) that checks whether atm; and the solution is
MyTM(time_t t): tm(MyTM(localtime(t))
I personally think that it is clumsy and that there should be a better way
to allow conditional expressions with cached values in the initializer list.
One could use a static member variable for that purpose but it is unsafe
when the application is multithreaded (apart from the fact that localtime is
unsafe itself, but it could be replaced with a safe function of your
choice).
Chris
Christopher
---
[ 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: gp.kiwi@gmail.com (Graeme Prentice)
Date: Sun, 12 Jun 2005 05:21:43 GMT Raw View
On Sat, 11 Jun 2005 21:42:53 GMT, "Krzysztof Zelechowski" wrote:
>
>Uzytkownik "Victor Bazarov" <v.Abazarov@comAcast.net> napisal w wiadomosci
>news:Irgqe.82265$NC6.55399@newsread1.mlpsca01.us.to.verio.net...
>> Hello,
>>
>> Recently in comp.lang.c++ (and several times before that in other
>> places) I've seen a request to call a function to do some work
>> at the moment of initialising a class, usually in the constructor
>> initialiser list. The request is something like
>>
>> struct A {
>> A(); // some other processing
>> };
>>
>> struct B : A {
>> B() : <<< do_something_here() >>> A() {}
>> };
>>
>> where 'do_something_here' could be a member of 'B' or any other
>
>Cannot, because B has not been constructed. You cannot call member
>functions of objects that have not been constructed yet.
>
>> function that might even be unrelated to B or A. The kludgy way
>> of solving this is to give 'A's constructor an argument and make
>> 'do_something_here()' to return something. It's cheating, in my
>> opinion, besides, it's not always possible if 'A' is not my class.
>>
>
>I had a similar problem when I wanted to derive from struct tm and construct
>with a value of type time_t via localtime();
>
>I cannot MyTM(time_t t): tm(*localtime(t))
>
>because localtime(t) can be 0; I had to use another constructor MyTM(tm
>*atm) that checks whether atm; and the solution is
>
>MyTM(time_t t): tm(MyTM(localtime(t))
>
>I personally think that it is clumsy and that there should be a better way
>to allow conditional expressions with cached values in the initializer list.
>One could use a static member variable for that purpose but it is unsafe
>when the application is multithreaded (apart from the fact that localtime is
>unsafe itself, but it could be replaced with a safe function of your
>choice).
Yeah, localtime, along with a few other C features, can't be called from
multiple threads. (How do you find out the thread-safety of "C" library
functions with GCC?)
Your solution looks like it might recurse forever. What's wrong with a
call to a simple inline function to check for the null pointer
inline tm fix(tm*pmt) { if (pmt) return *pmt; else return tm(); }
MyTM(time_t t): tm(fix(*localtime(t)))
Regarding caching, if you can't use a static variable and don't want to
use synchronization or a non-static member variable (in a
first-in-construction-order base class using Daphne Pfister's method),
you can always add a dummy parameter to the constructor parameter list
that is a reference to whatever kind of temporary (i.e. stack based)
object you like - initialized with a default value.
As far as I can see, there's already adequate solutions to the OP's
(Victor's) problem. In most cases, if the base class constructor
requires some setup or selection done first, it's seems logical that the
base class constructor should enforce that and do it itself, rather than
rely on the derived class to do it.
Your inheritance from struct tm is potentially unsafe because "C"
functions are likely to assume that they can do what they like with the
entire content of tm (including memset it to zero) whereas the derived
class may actually be using some of the "unused" part (if any) of struct
tm for its own data. It would be useful if this kind of "overlap" was
prohibited if the base class was declared with the struct keyword
instead of the class keyword, or if "overlapping" could be turned off
with a compiler switch or #pragma or to allow structs to be declared
with "C" language linkage that meant they were never overlapped.
Graeme
---
[ 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: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Sun, 12 Jun 2005 06:11:49 GMT Raw View
"Krzysztof Zelechowski" wrote:
> Uzytkownik "Victor Bazarov" <v.Abazarov@comAcast.net> napisal w
> wiadomosci
> news:Irgqe.82265$NC6.55399@newsread1.mlpsca01.us.to.verio.net...
>> Hello,
>>
>> Recently in comp.lang.c++ (and several times before that in other
>> places) I've seen a request to call a function to do some work
>> at the moment of initialising a class, usually in the constructor
>> initialiser list. The request is something like
>>
>> struct A {
>> A(); // some other processing
>> };
>>
>> struct B : A {
>> B() : <<< do_something_here() >>> A() {}
>> };
>>
>> where 'do_something_here' could be a member of 'B' or any other
>
> Cannot, because B has not been constructed. You cannot call member
> functions of objects that have not been constructed yet.
Yes, I can, if it's a static member.
> [...]
V
---
[ 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: kon@iki.fi (Kalle Olavi Niemitalo)
Date: Sun, 12 Jun 2005 16:06:50 GMT Raw View
v.Abazarov@comAcast.net ("Victor Bazarov") writes:
>> As B& is implicitly convertible to void&,
>
> I somehow think there is no such thing as 'void&'... Is there?
Oops. Make it "B* is implicitly convertible to void*", then.
---
[ 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 ]