www.digitalmars.com         C & C++   DMDScript  

D - Structs and compound return types

reply Russ Lewis <russ deming-os.org> writes:
Some functions need to return complex data.  Sometimes it makes sense to
do that as a struct (because that struct is defined elsewhere), but
sometimes not.  Occasionally, I run across situations where the most
straightforward thing to do is to return a custom, function-specific
struct.  I'm wondering what you all think of the following code:


struct { int i; char *str; } foo()
{
    return {0,"blah"};
};


Obvious pluses:
* No need to define separate struct
* Easy return syntax
* foo().i and foo().str give reasonable and understandable values
* As compared to pass-return-by-pointer, no need to check if pointer is
NULL or to create a dummy variable.

Obvious minuses:
* Harder to read?
* How can a caller store both variables?
    Maybe:
       foo.return val = foo();


Other thoughts?  I know that this won't make it into any early version
of D, does anyone think that it might be useful?
Sep 18 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
The multiple return value issue has been discussed in another thread here.
I'm not sure using an implicit struct is a good idea, since you can only
pick off one of the members. -Walter

"Russ Lewis" <russ deming-os.org> wrote in message
news:3BA7A419.9D08DD3E deming-os.org...
 Some functions need to return complex data.  Sometimes it makes sense to
 do that as a struct (because that struct is defined elsewhere), but
 sometimes not.  Occasionally, I run across situations where the most
 straightforward thing to do is to return a custom, function-specific
 struct.  I'm wondering what you all think of the following code:


 struct { int i; char *str; } foo()
 {
     return {0,"blah"};
 };


 Obvious pluses:
 * No need to define separate struct
 * Easy return syntax
 * foo().i and foo().str give reasonable and understandable values
 * As compared to pass-return-by-pointer, no need to check if pointer is
 NULL or to create a dummy variable.

 Obvious minuses:
 * Harder to read?
 * How can a caller store both variables?
     Maybe:
        foo.return val = foo();


 Other thoughts?  I know that this won't make it into any early version
 of D, does anyone think that it might be useful?
Sep 18 2001
parent Russ Lewis <russ deming-os.org> writes:
Walter wrote:

 The multiple return value issue has been discussed in another thread here.
 I'm not sure using an implicit struct is a good idea, since you can only
 pick off one of the members. -Walter
Right, I read (some of that), but got lost when they started getting into some of the odder ways to name return values. I'm hoping that there is a good way to do this, staying in the C/D paradigm, and not causing headaches for either the compiler or code maintainers.
Sep 18 2001
prev sibling next sibling parent reply Russell Bornschlegel <kaleja estarcion.com> writes:
Russ Lewis wrote:
 
 Some functions need to return complex data.  Sometimes it makes sense to
 do that as a struct (because that struct is defined elsewhere), but
 sometimes not.  Occasionally, I run across situations where the most
 straightforward thing to do is to return a custom, function-specific
 struct.  I'm wondering what you all think of the following code:
 
 struct { int i; char *str; } foo()
 {
     return {0,"blah"};
 };
I've said it before, but I think it's good practice on a number of levels to go ahead and declare that struct and give it a name at the point where you declare foo(): struct foo_return { int i; char* str; }; foo_return foo( void ); and then invoke it as: foo_return val = foo(); or: if (foo().i == BARBAZ) { ... } This form actually _saves_ keystrokes in the case where foo() appears in both a .h and a .cpp file, because rather than write the struct out explicitly in the .cpp, you use the name form. This is less error prone, and, importantly, it works in today's compilers. -Russell B
Sep 18 2001
parent reply Russ Lewis <russ deming-os.org> writes:
What about the foo.return syntax?  Then the return type of foo() can be
referenced.  It's not unlike foo_return...but it's defined by the language
rather than explicitly by the programmer.

In such an environment, how would you differentiate between overloaded
functions?

In fact, how does that work currently in C++/D???
Sep 18 2001
parent John Fletcher <J.P.Fletcher aston.ac.uk> writes:
Russ Lewis wrote:

 What about the foo.return syntax?  Then the return type of foo() can be
 referenced.  It's not unlike foo_return...but it's defined by the language
 rather than explicitly by the programmer.

 In such an environment, how would you differentiate between overloaded
 functions?

 In fact, how does that work currently in C++/D??
WARNING: This solution uses templates. I have been using a tuple structure in C++ which is one of the things in the Lambda Library. ( See http://lambda.cs.utu.fi/ ) . A tuple library is also available in Boost. Suppose I want to return two ints. I can do a typedef like this: typedef tuple<int,int> tuple_int_int; The function implementaion is like this: tuple_int_int foo() { int i = 0; int j = 1; return make_tuple(i, j); } The calling program uses a reference tuple: typedef tuple<int&,int&> tuple_intR_intR; A variable is declared like this: int a, b; tuple_intR_intR a_b = make_tuple(ref(a), ref(b)); The call looks like this a_b = foo(); which returns the value of i in a and the value of j in b. I like it. John
Sep 20 2001
prev sibling parent reply "Richard Krehbiel" <rich kastle.com> writes:
"Russ Lewis" <russ deming-os.org> wrote in message
news:3BA7A419.9D08DD3E deming-os.org...
 Some functions need to return complex data.  Sometimes it makes sense to
 do that as a struct (because that struct is defined elsewhere), but
 sometimes not.  Occasionally, I run across situations where the most
 straightforward thing to do is to return a custom, function-specific
 struct.  I'm wondering what you all think of the following code:


 struct { int i; char *str; } foo()
 {
     return {0,"blah"};
 };
This is already valid in standard C. Of course, as an anonymous struct type, in standard C you can't declare variables to which the return value can be assigned. But you can with GCC, which can declare the variable using typeof. -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 home.com (personal)
Sep 21 2001
parent reply Russ Lewis <russ deming-os.org> writes:
Richard Krehbiel wrote:

 This is already valid in standard C.
I tried it on one compiler, and it was a syntax error. Have to try it on another. Anybody out there know of *any* compiler that perfectly conforms to the C and C++ standards? (grrr)
 Of course, as an anonymous struct type, in standard C you can't declare
 variables to which the return value can be assigned.  But you can with GCC,
 which can declare the variable using typeof.
I'm not familiar with this. Can you explain?
Sep 21 2001
parent reply "Richard Krehbiel" <rich kastle.com> writes:
"Russ Lewis" <russ deming-os.org> wrote in message
news:3BAB8E1A.1AA728F9 deming-os.org...
 Richard Krehbiel wrote:

 This is already valid in standard C.
I tried it on one compiler, and it was a syntax error. Have to try it on another. Anybody out there know of *any* compiler that perfectly conforms
to
 the C and C++ standards?  (grrr)
Um, okay I goofed on that one. It's almost legal C to define a function like this: struct { int i; double d; } a_to_n(char *s) { ...but it gets unusable very quickly because you can't pronounce the return type of the function in order to return a value. So, just give the struct a name... struct a_to_n_yeilds { int i; double d; } a_to_n(char *s) { struct a_to_n_yeilds y; y.i = 10; y.d = 10.0; return y; }
 Of course, as an anonymous struct type, in standard C you can't declare
 variables to which the return value can be assigned.  But you can with
GCC,
 which can declare the variable using typeof.
I'm not familiar with this. Can you explain?
GCC has a keyword that lets you extract the type of an arbitrary expression for use in declaring some other object. struct { int i; double d; } a_to_n(char *s) { // Evaluate the type of the return value of a function call // to myself and use it to declare y typeof(a_to_n("")) y; y.i = 10; y.d = 10.0; return y; } -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 home.com (personal)
Sep 25 2001
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Richard Krehbiel wrote:

 Of course, as an anonymous struct type, in standard C you can't declare
 variables to which the return value can be assigned.  But you can with
GCC,
 which can declare the variable using typeof.
I'm not familiar with this. Can you explain?
GCC has a keyword that lets you extract the type of an arbitrary expression for use in declaring some other object. struct { int i; double d; } a_to_n(char *s) { // Evaluate the type of the return value of a function call // to myself and use it to declare y typeof(a_to_n("")) y; y.i = 10; y.d = 10.0; return y; }
I like :) This is pretty much equivalent to the foo.return syntax, except that it has the bonus of allowing you to differentiate between overloaded functions. This is something that I would very much like in D, eventually!
Sep 25 2001
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
As soon as I hit "Send" I realized I had a quibble.  Sorry for the double-post.

While I like the fact that GCC has this feature, and I like the fact that the
syntax handles overloading well, I don't like the "feel" of the syntax.  I still
think it should be a property.  Walter has said that there will be a property
".class or some such" (see "finding the class of an object" thread).  If we
call it
.typeof, then it works in many situations:

class Foo {};

struct { int a; int b; } bar(char *);

Foo a;
a.typeof b;
bar(char*).typeof retVal;
Sep 25 2001
parent a <a b.c> writes:
Russ Lewis wrote:
 
 As soon as I hit "Send" I realized I had a quibble.  Sorry for the double-post.
 
 While I like the fact that GCC has this feature, and I like the fact that the
 syntax handles overloading well, I don't like the "feel" of the syntax.  I
still
 think it should be a property.  Walter has said that there will be a property
 ".class or some such" (see "finding the class of an object" thread).  If we
call it
 .typeof, then it works in many situations:
 
 class Foo {};
 
 struct { int a; int b; } bar(char *);
 
 Foo a;
 a.typeof b;
 bar(char*).typeof retVal;
Depending on how generics get implemented, this could be very useful. It might make some parts of generic programming a lot easier. Dan
Sep 25 2001