return type sugar (orthogonal to auto foo() {} )

192 views
Skip to first unread message

walter1234

unread,
Jun 12, 2014, 6:16:04 AM6/12/14
to std-pr...@isocpp.org
Coming back to C++ from Rust, one thing begin to miss is the 2way type inference: its a nice choice on their part, you write the types in the signature, then the types in the body are inferred.

But perhaps a significant amount of this use could be covered by having sugar to access the declared return type of a function within its own body.

imagine

auto foo(  args...  )->decltype(....some expression based on args...) {

      return_type  accumulator;     // 'return_type' is a shortcut for whatever this functions declared return type is..
      ... do stuff with accumulator...

     return accumulator.
}

ways of doing that without a new keyword, perhaps 'decltype(return)' , any other ideas..
In some ways this would go beyond what rust currently does. (rust can't yet use an expression for the return type, although making it generic often works because of how the return types are inferred by callers)

Maurice Bos

unread,
Jun 12, 2014, 9:49:51 AM6/12/14
to std-pr...@isocpp.org
decltype(return) sounds good. I wished quite a few times I could've
written this. (D has it in the form of typeof(return):
http://dlang.org/declaration.html#Typeof)
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposal...@isocpp.org.
> To post to this group, send email to std-pr...@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.

Sebastian Gesemann

unread,
Jun 12, 2014, 10:10:48 AM6/12/14
to std-pr...@isocpp.org
I'm not sure about the utility for such a short cut -- given the fact
that in C++14 you can do something like this:

// note: no trailing return type
auto foo(int x, double y) {
return x+y;
}

Compared to what you suggest, this is the other way around: The return
type can be deduced from whatever the function returns.

Mikhail Semenov

unread,
Jun 12, 2014, 11:03:06 AM6/12/14
to std-pr...@isocpp.org
You can already write:
auto foo(int x, double y)->decltype(x+y)
{
    ...
}


Sebastian Gesemann

unread,
Jun 12, 2014, 12:00:09 PM6/12/14
to std-pr...@isocpp.org
On Thu, Jun 12, 2014 at 5:03 PM, Mikhail Semenov wrote:
> You can already write:
> auto foo(int x, double y)->decltype(x+y)
> {
> ...
> }

Everybody knows that. The original poster wants a way to refer to the
return in the function body type without repeating that expression.

Obviously, one way of writing this function so that x+y is only
mentioned once is to make use of C++14's return type deduction. But
from the looks of the topic of this discussion ("...orthogonal to auto
foo() {}"), the OP already knew that.

So, I'm not really sure what the point of your response was.

Cheers!
sg

walter1234

unread,
Jun 12, 2014, 3:14:20 PM6/12/14
to std-pr...@isocpp.org
auto foo(...) {return...}   is certainly a great thing to have.

the benefit of the type being in the signature however, is discoverability and documentation - you may see many single line function prototypes in a header, or you may have function bodies hidden.   You may search for a function by virtue of knowing what you want it to create.

The use that made me think of this was prototyping, even when functions are inline and in headers, you still sometimes want to prototype them above so that other functions can refer to them. Sometimes you want to separate out ".h" with just prototypes and ".inl" with inline function bodies.

I realise it might be possible to address the 'documentation' issue with an IDE, which can deduce the types and show you in autocomplete/or function browsers.

mitc...@gmail.com

unread,
Jun 13, 2014, 4:04:35 AM6/13/14
to std-pr...@isocpp.org
How about:

auto foo(int bar, float baz) -> decltype(bar + baz) {
   
decltype(foo(bar, baz)) res = bar + baz;
   
return res;
}


this way you don't have to repeat the expression, you only need to change the type of "res" if the function name / parameters change.  Having decltype(return) be just syntax sugar for the above would be nice and easy to do, so I think it would be nice to have a proposal for this.

David Rodríguez Ibeas

unread,
Jun 13, 2014, 9:12:39 AM6/13/14
to std-pr...@isocpp.org
On Thu, Jun 12, 2014 at 3:14 PM, walter1234 <walt...@gmail.com> wrote:
auto foo(...) {return...}   is certainly a great thing to have.

the benefit of the type being in the signature however, is discoverability and documentation - 

... and being able to use the return type in an SFINAE context. [Personally I believe that library code *should* always spell out the return type in the signature, trailing return type is fine, return type being deduced not so much].

This is a contrived example, but is concise enough to be sent over email:

std::string f(int);
void          f(double);

template <typename T>
auto g(T value) {
    return f(value);
}

template <typename T>
auto h(T value) -> decltype(g(value).size())
{
    return g(type).size();
}
template <typename T>
size_t h(T value, ...) {
    return size_t();
}

int main() {
    h(1.0);       // hard error!!
}

If the return type of 'g' had not been deduced the above would have SFINAE-d out the first template and called the second overload of 'h'.

    David

Andrzej Krzemieński

unread,
Jun 13, 2014, 12:24:28 PM6/13/14
to std-pr...@isocpp.org
How about doing it the Go style:
 
auto foo(  args...  ) -> decltype(....some expression based on args...) accumulator
{   
  do_stuff_with(accumulator);
  return accumulator.
}
 

Andrzej Krzemieński

unread,
Jun 13, 2014, 12:25:38 PM6/13/14
to std-pr...@isocpp.org
Or even w/o return statement because it is obvious what we return:
 
auto foo( args... ) -> decltype(....some expression based on args...) accumulator
{
   do_stuff_with(accumulator);
   // no return (and no UB)
}

walter lynsdale

unread,
Jun 13, 2014, 10:37:43 PM6/13/14
to std-pr...@isocpp.org
the go-like idea is interesting, 
would the grammar work if you were able to initialise 'accumulator' with an expression based on the inputs ?

I think the decltype(return) would have more uses , e.g. accessing associated types aswell ?


--

---
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/wdX31-nWSnc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.

Andrzej Krzemieński

unread,
Jun 16, 2014, 7:29:59 AM6/16/14
to std-pr...@isocpp.org


W dniu sobota, 14 czerwca 2014 04:37:43 UTC+2 użytkownik walter1234 napisał:
the go-like idea is interesting, 
would the grammar work if you were able to initialise 'accumulator' with an expression based on the inputs ?

We are fantasizing about a potential addition, so we can decide on whatever we want.


I think the decltype(return) would have more uses , e.g. accessing associated types aswell ?

The following work today:

struct ToolBox
{
  typedef int Tool;
  // declarations
}

auto ToolBox::getTool() -> Tool // no need for ToolBox::Tool
{/*...*/}

auto ToolBox::make(X x, Y y) -> decltype(x + y)
{/*...*/}

Given that the trailing return type can access both names associated with the class and argument names, it should be possible to have the "default return variable" make use of these.

Regards,
&rzej

 
Reply all
Reply to author
Forward
0 new messages