Initializing a struct while calling a function

Pages: 12
Suppose I have a struct
1
2
3
4
5
6
struct MyStruct
{
    int a;
    int b;
    int c;
};

And a function that takes this struct as a parameter
1
2
3
4
void MyFunc(MyStruct bar)
{
    ...
}

At the moment my program is calling the function like so:
1
2
3
4
5
6
main()
{
    MyStruct foo = { 1, 2, 3 };
    MyFunc(foo);
    ...
}

I know its trivial but can these two lines be merged into a single statement?

Thanks in advance.
Last edited on
No. Not without adding a constructor to MyStruct.
You can do this:

MyFunc( (MyStruct){1, 2, 3} );
That was going to be my reply - but compound literals are not ISO standard.


[edit]
I mean ISO C++ standard
Last edited on
I see. Good point.
For zeolite, following on helios's suggestion:
1
2
3
4
5
6
7
struct MyStruct
{
    int a;
    int b;
    int c;
    MyStruct( int a = 0, int b = 0, int c = 0 ): a(a), b(b), c(c) {}
};

The zeros are default arguments... you can set them to whatever you like. Then:
1
2
3
4
5
int main()
{
    MyFunc(MyStruct( 1, 2, 3 ));
    ...
}

This, of course, is C++ only, so if you are using C it won't work. JSYK.

Hope this helps.
Duoas: it also means that MyStruct is no longer a POD type.

A POD type in C++ is an aggregate class that contains only POD types as members, has no user-defined destructor, no user-defined copy assignment operator, and no nonstatic members of pointer-to-member type.
http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.7 seems to indicate that it can have *no* constructors.

In addition, a POD type can't have constructors, virtual functions, base classes, or an overloaded assignment operator.
Definition of what a POD is seems rather arbitrary anyway. Does it really matter?
http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.7 seems to indicate that it can have *no* constructors.

It doesn't matter what parashift states. They are wrong. What matters, is the information contained in the ISO std, yes?

From the ISO std:
1
2
An object of POD4) type (3.9) shall occupy
contiguous bytes of storage.


Yes it matters and aren't you the one who brought it up in the first place? If you scan the std you'll see references to POD all over. I did a quick scan and found about 50 references to rules relating specifically to POD types.

From the ISO std:
"A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct,
non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator
and no user-defined destructor."
Last edited on
kempofighter, I think the confusion comes from the definition of "aggregate type" (used by helios, above).

From ISO/IEC 14882:1998(E), section 8.5.1, paragraph 1 (emphasis mine):

An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or pro-
tected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).




Last edited on
Definition of what a POD is seems rather arbitrary anyway. Does it really matter?


In this case, almost certainly not. But it is important when interfacing with C APIs. It is very easy to accidentally change a POD struct into a non-POD struct and screw up compatibility. For instance, you can memcpy a POD struct, but cannot do that with non-POD types. I know this because I recently screwed up some code this way. Learning from your own mistakes is a bitch. :-)
For instance, you can memcpy a POD struct, but cannot do that with non-POD types.
Wait, are you saying no struct with a constructor can be memcpy()ed? How does having a function is in a struct's namespace affect the adjacency of the struct's members?
Wait, are you saying no struct with a constructor can be memcpy()ed? How does having a function is in a struct's namespace affect the adjacency of the struct's members?


It is undefined behavior to memcpy non-POD types. Or, put another way, the result of memcpy in C++ is only defined for POD types.


Well I hate being wrong but I guess I am. I see what the FAQ writer is saying. The reading of the std is pretty gnarly in that case since you have to read multiple sections just to understand what a POD type is.
I agree that it is pretty stupid for it to make any difference...

You can use the simple C way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

struct MyStruct
  {
  int a;
  int b;
  int c;
  };

struct MyStruct MyStruct( int a, int b, int c )
  {
  struct MyStruct result;
  result.a = a;
  result.b = b;
  result.c = c;
  return result;
  }

void print_MyStruct( struct MyStruct a )
  {
  printf( "a = %d\nb = %d\nc = %d\n", a.a, a.b, a.c );
  }

int main()
  {
  print_MyStruct(MyStruct( 1, 2, 3 ));
  return 0;
  }

Pure C. The trick is just to remember that you must prefix the structure name with 'struct'.

Hope this helps.
Can you have a function named the same thing as the struct like that?
Yes. Structs have a separate namespace in C. It works in C++ too, but you must, as in C, use the 'struct' keyword to indicate that you want the struct tag namespace over the normal identifier namespace.

Compile it and see it work. ;-)
Cheers for the code sample Duoas. I added the lines
1
2
3
4
5
6
7
8
struct MyStruct MyStruct( int a, int b, int c )
  {
  struct MyStruct result;
  result.a = a;
  result.b = b;
  result.c = c;
  return result;
  }

and it compiles under Visual C++ 2008 Express Edition...

However, if I then add

vector<MyStruct> v;

then MS VC++ generates the error

'MyStruct' is not a valid template type argument for parameter '_Ty'

This error disappears if I comment out the funciton MyStruct. I am not sure what is the cause of this.
Pages: 12