Why can't we automatically return return types?

I recently worked with a friend who wanted to make C ++ more Haskell-y, and we need a function that basically looks like this:

auto sum(auto a, auto b) { return a + b; } 

Apparently, I cannot use auto as a parameter type, so I changed it to this:

 template<class A, class B> auto sum(A a, B b) { return a + b; } 

But that doesn't work either. What we finally understood, we need this:

 template<class A, class B> auto sum(A a, B b) -> decltype(a + b) { return a + b; } 

So my question is, what's the point? Isn't decltype just repeating the information, since the compiler can just look at the return statement?

I thought it might be necessary, so we can just include the header file:

 template<class A, class B> auto sum(A a, B b) -> decltype(a + b); 

... but we still cannot use such patterns.

The other thing I considered was that the compiler might be simpler, but it seems like it will actually be more complicated.

Case 1: with decltype

  • Find out the type of decltype
  • Find out return types
  • See if they match

Case 2: Without decltype

  • Find out return types
  • See if they match

So, with these things in mind, what is the point of return type with decltype ?

+51
c ++ c ++ 11
Sep 28 '11 at 9:26 a.m.
source share
5 answers

What if we have the following:

 template<class A, class B, class C> auto sum(A a, B b, C c) { if (rand () == 0) return a + b; // do something else... return a + c; } 

.. where the expressions a + b and a + c give different types of results. What should the compiler decide to set as the return type for this function and why? This case is already under consideration by C ++ 11 lambdas, which allow omitting the return type if return can be inferred to the same type (a standard quote from NB is required), some sources claim that only one return expression is allowed, and that this is a gcc glitch )




The technical reason is that C ++ allows you to define and declare individual ones.

 template<class A, class B> auto sum(A a, B b) -> decltype(a + b); template<class A, class B> auto sum(A a, B b) -> decltype(a + b) { } 

The template definition may be in the header. Or it may be in another file, so you don’t have to wade through pages and function definition pages when viewing the interface.

C ++ should consider all the possibilities. Limiting the return types of return values ​​only to the definition of functions means that you cannot do something simple:

 template<class A, class B> class Foo { auto sum(A a, B b) -> decltype(a + b); } template<class A, class B> auto Foo<A, B>::sum(A a, B b) -> decltype(a + b) { } 
+38
Sep 28 '11 at 9:31
source share
β€” -

but we still cannot use such patterns.

First, return types are not just patterns. They work for all functions. Secondly, who says? This is a perfectly legal code:

 template<class A, class B> auto sum(A a, B b) -> decltype(a + b); template<class A, class B> auto sum(A a, B b) -> decltype(a + b) { } 

The template definition may be in the header. Or it may be in another file, so you don’t have to wade through pages and function definition pages when viewing the interface.

C ++ should consider all the possibilities. Limiting the return types of return values ​​only to the definition of functions means that you cannot do something simple:

 template<class A, class B> class Foo { auto sum(A a, B b) -> decltype(a + b); } template<class A, class B> auto Foo<A, B>::sum(A a, B b) -> decltype(a + b) { } 

And this is quite common for many programmers. There is nothing wrong with wanting to encode this path.

The only reason lambdas leave without a return type is because they must have a function body defined with a definition. If you have limited return types to only those functions in which the definition was defined, you cannot use any of the above cases.

+8
Sep 28 '11 at 21:45
source share

There are no technical reasons why this is not possible. The main reason that they are not connected is that the C ++ language moves very slowly, and it takes a lot of time to add functions.

You can get good syntax with lambdas (but you cannot have templacized arguments in lambdas, again without a good reason).

 auto foo = [](int a, double b) { return a + b; }; 

Yes, there are cases when the return type cannot be automatically inferred. Just like in lambda, it might just be a requirement to declare a return type in these ambiguous cases.

At the moment, the restrictions are so arbitrary that they are difficult to upset. Also see Deleting concepts to add frustration.

+5
Sep 29 2018-11-11T00:
source share

On a blog post from Dave Abrahams, he discusses a suggestion about having this function syntax:

 []min(x, y) { return x < y ? x : y } 

This is based on a possible proposal for polymorphic lambda. He also started work here on updating clang to support this syntax.

0
Jun 21 '12 at 16:13
source share

Little hope to persuade the committee to add such a language function, although there are no technical obstacles. But perhaps you can convince the GCC group to add a compiler extension.

-one
Oct 05 2018-11-11T00:
source share



All Articles