Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What does this struct line do?

104 views
Skip to first unread message

Doug Mika

unread,
Jul 23, 2015, 4:03:22 PM7/23/15
to
Hi, I of course know about structs, but whenever I see the word "struct" I expect a certain pattern to follow (ie. the definition of a struct). So seeing this line, I am quite perplexed. What does it mean?

struct std::tm * ptm = std::localtime(&tt);

It is taken from the example located at:
http://www.cplusplus.com/reference/mutex/timed_mutex/try_lock_until/

Thanks

Ian Collins

unread,
Jul 23, 2015, 4:14:01 PM7/23/15
to
Doug Mika wrote:

[Please wrap your lines!]

> Hi, I of course know about structs, but whenever I see the word
> "struct" I expect a certain pattern to follow (ie. the definition of
> a struct). So seeing this line, I am quite perplexed. What does it
> mean?
>
> struct std::tm * ptm = std::localtime(&tt);

There are cases in C++ where some additional disambiguation is required,
for example where a struct and a function have the same name.

This example isn't one of them... Both "struct" and in my opinion the
use of std:: are superfluous in this case.

--
Ian Collins

Vir Campestris

unread,
Jul 23, 2015, 4:47:51 PM7/23/15
to
My guess is it was written by an old C programmer, where "struct" is
more often needed.

Which std:: do you think is superfluous?

Andy

Victor Bazarov

unread,
Jul 23, 2015, 4:58:35 PM7/23/15
to
Both, probably. Regardless of how the header was included, 'struct tm'
and 'localtime' function are likely declared in the global namespace
anyway (as well as in 'std').

V
--
I do not respond to top-posted replies, please don't ask

red floyd

unread,
Jul 23, 2015, 5:17:37 PM7/23/15
to
It's declaring a point to a std::tm, and initializing it with the
return value from std::localtime.

std::tm and std::localtime are defined in <ctime>

Ian is right that the "struct" is superfluous (it's a C-ism).
I believe he's wrong about the std:: being superfluous.


Ian Collins

unread,
Jul 23, 2015, 5:46:02 PM7/23/15
to
Whether the std:: is superfluous depends on whether <ctime> or <time.h>
was included. <ctime> will bring the symbols form <time.h> into the std
namespace.

--
Ian Collins

Bo Persson

unread,
Jul 23, 2015, 6:38:29 PM7/23/15
to
Yes, it's likely a C-ism left over.

In C you can write

struct tm* = ...

even if the header is not included, as 'struct tm' works as a forward
delaration when used to declare a pointer. Not so if we add std:: to it.


Bo Persson




Alf P. Steinbach

unread,
Jul 23, 2015, 7:45:22 PM7/23/15
to
To be precise, the C++ <ctime> header brings the symbols from the C
<time.h> header into namespace std, and possibly also places them in the
global namespace. The C++ <time.h> header (in C++14 specified in §D.5/2)
brings the namespace std symbols from <ctime> into the global namespace,
possibly without providing the names in namespace std...

The C++14 standard gives this example in D5:

"The header <cstdlib> assuredly provides its declarations and
definitions within the namespace std. It may also provide these names
within the global namespace. The header <stdlib.h> assuredly provides
the same declarations and definitions within the global namespace, much
as in the C Standard. It may also provide these names within the
namespace std."

The upshot is that code that includes e.g. <ctime> may work with one
compiler when using an unqualified name, but may fail to compile with
some other compiler, both standard-conforming.

Code that includes <time.h> and uses std-qualified names may likewise be
non-portable, but it's less likely that <time.h>-based code qualifies
names than that <ctime>-based code doesn't qualify names, and it's less
likely that <time.h> places names in namespace std than that <ctime> or
some other other header places names in the global namespace.
Multiplying those less-likelies it's much less likely overall.

And so, the chance of inadvertently writing non-portable code is
minimized by using the ".h" headers. It also yields less verbose code.
And it teaches one to generally avoid using the names defined by the C
library, for other things, i.e. treating them as reserved names.


Cheers,

- Alf

--
Using Thunderbird as Usenet client, Eternal September as NNTP server.

Richard Damon

unread,
Jul 24, 2015, 1:26:01 AM7/24/15
to
The struct wouldn't be superfluous if the definition of std::tm hasn't
been introduced yet (making it a forward declaration).

Lőrinczy Zsigmond

unread,
Jul 24, 2015, 2:44:17 AM7/24/15
to
> The upshot is that code that includes e.g. <ctime> may work with one
> compiler when using an unqualified name, but may fail to compile with
> some other compiler, both standard-conforming.

Well, let's not forget that C++ haven't reached mature status yet
(its only 30 years old, after all), time will solve this question.

Öö Tiib

unread,
Jul 24, 2015, 4:45:50 AM7/24/15
to
That is not a forward-declaration of 'std::tm' in C++. If it hasn't been introduced
yet then the compiler should not parse it. Forward-declaration of 'std::tm' looks
like that in C++:

namespace std { struct tm; }

std::tm* ptm;

woodb...@gmail.com

unread,
Jul 24, 2015, 11:31:09 AM7/24/15
to
I took similar advice from you a few years ago and stopped
using ctime and friends. I would write the code in question as:

#include <time.h>

::tm* ptm = ::localtime(&tt);


Brian
Ebenezer Enterprises - With "friends" like Obama who needs enemies?
http://webEbenezer.net

Richard

unread,
Jul 26, 2015, 5:05:27 PM7/26/15
to
[Please do not mail me a copy of your followup]

Doug Mika <doug...@gmail.com> spake the secret code
<47f25c65-bfe4-433a...@googlegroups.com> thusly:

>struct std::tm * ptm = std::localtime(&tt);

This is basically a C-ism and the 'struct' is unnecessary in C++.

In C, without a typedef you have to say 'struct foo' all the time to
refer to the name 'foo' as the name of a structure. This is why you
often see this in C:

typedef struct tag_foo foo;

or this

typedef struct tag_foo {
int member;
} foo;

In C, you can't write:

struct foo {
int member;
};

foo *p = (foo *) malloc(sizeof(foo));

Instead you must either introduce a typedef or you must write:

struct foo *p = (struct foo *) malloc(sizeof(struct foo));

This code is perfectly legal in C++, but the use of 'struct' is
redundant here because C++ introduces new names for types whenever
they are declared with struct, union, or class.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

pip010

unread,
Aug 3, 2015, 8:27:15 AM8/3/15
to
typedef class and struct are interchangeable.
does it help if you read with typedef instead of struct ?

Victor Bazarov

unread,
Aug 3, 2015, 9:32:21 AM8/3/15
to
Are you suggesting that the line in the original post is equivalent to

typedef std::tm * ptm = std::localtime(&tt);

?

Öö Tiib

unread,
Aug 3, 2015, 9:43:48 AM8/3/15
to
Can't be. It is nonsense that should not parse without diagnostic.
Perhaps he meant:

typename std::tm * ptm = std::localtime(&tt);

That should parse if 'std::tm' and 'std::localtime' are declared.
0 new messages