I'm curious what the differences between the type inference of Scala and C++11 are. In which situations do I have to specify the types in one language but not in the other? One difference seems to be the return type of functions which always have to be specified in C++11, although decltype
and the new function syntax with a trailing return type allow to specify a inferred type.

- 4,725
- 2
- 28
- 47
2 Answers
C++ cannot infer such anonymous functions:
// this wont work*
void somefunc(std::vector<int>& v)
{
std::for_each(v.begin(), v.end(), [](auto &x) { x++; });
}
// /\
// ------ I want this to be infered
whereas Scala can:
def somefunc(v: Vector[Int]) = v.map(x => x +1)
*not sure that I've dealt correctly with C++ code syntax, I don't insult language, but it's really cryptic. If I've made a mistake, correct me, please

- 353,942
- 115
- 666
- 851

- 62,329
- 13
- 183
- 228
-
3You are comparing a method call on a vector with a function. An equivalent Scala method should look like `map(v, x => x + 1)` (with an appropriate `map` method). In this case, Scala’s inference fails as well. However, this will work: `map(v)(x => x + 1)`. – Debilski Apr 21 '12 at 11:51
-
@Debilski also, if we talk about exact comparison: Scala version creates a new collection (and accepts vector by value), while C++ version updates vector in place. – om-nom-nom Apr 21 '12 at 12:24
-
1But the point here is differences in type inference – not how collections work. I think it is perfectly possible to contrast type inference, it is just your example which gives a wrong impression. – Debilski Apr 21 '12 at 17:22
-
2In the C++ example the type of `x` could be specified by `decltype(*v.begin())`, see: http://stackoverflow.com/a/5713038/460387 But that is also not type inference... – Frank S. Thomas Apr 21 '12 at 18:53
-
@om-nom-nom Scala neither creates new collection in that case nor accepts vector by value. Please do not misguide people. – Grozz Apr 22 '12 at 00:27
-
@Grozz You really surprised me. Is there is possibility to pass value to function *by reference* in Scala? And map *is* creates new collection. If you don't trust me, try this code `val oldC = (1 to 10).toList; val newC = oldC.map(_+1);` and look what value has oldC after map. – om-nom-nom Apr 22 '12 at 00:33
-
@om-nom-nom well, we could mean different things by passes-by-value, because it passes pointer to Vector by value, but not the Vector itself. As for map, you are right, sorry, I was under the impression that it creates an iterator as any sane (C#) language implementation would do. – Grozz Apr 22 '12 at 05:08
-
C++14 has automatic argument type inference. So, `std::for_each(v.begin(), v.end(), [](auto &x) { x++; });` should work in C++14. – Soheil Hassas Yeganeh Jun 11 '14 at 16:56
In essence, C++ inference is simplistic compared to the grown ups.
Functional languages generally something close to Hindley/Milner which is pretty close to solving an equation systems and allow to have unknowns on both sides of the fence.
On the contrary, C++ expect to be able to know the type of any inner expression and from that deduce the type of the outer expression. It's a strictly one way inference, meaning that:
auto x = foo(1, 2);
works as expected as long as there is a foo
accepting integers and returning non-void. However, as demonstrated by om-nom-nom:
foo(1, [](auto x) { ++x; });
Will not work, because you cannot go backward and use the purported type of foo
to deduce the type of the lambda.
The reason behind is that C++ uses overloads of functions, meaning that several definitions of foo
could exist, and you actually need to know the types of the arguments to elect the right one. Since in general the above expression would be undecidable, it is forbidden even in limited cases it could have been allowed to avoid future maintenance hell and people never knowing when or not it can be used.

- 353,942
- 115
- 666
- 851

- 287,565
- 48
- 449
- 722
-
4For the sake of contrasting C++11 and Scala: Scala also does method overloading (and does not use Hindley–Milner either). – Debilski Apr 21 '12 at 11:28
-
@Debilski: Ah, interesting. I had thought Scala closer to Haskell. Guess that is what I get from cursory reading. Thanks for calling it out. – Matthieu M. Apr 21 '12 at 12:22
-
@MatthieuM. Scala has subtyping, which makes its type system more powerful, but consequently makes its inference abilities weaker. (Haskell does not have subtyping, unless you count superclass constraints on typeclasses) – Dan Burton Apr 21 '12 at 16:12
-
-1. "compare to the grown ups" is foolishly condescending at best. – Jerry Coffin Apr 21 '12 at 17:04
-
7Is it ? I would say not. C++ type inference is the simplest inference that exist. It is useful, but is definitely simplistic compared to Hindley/Milner. – Matthieu M. Apr 21 '12 at 17:11
-
Yes, it's simple. No, "grown up" doesn't imply complex. As @Debilski already pointed out, Scala doesn't do Hindley-Milner either. – Jerry Coffin Apr 21 '12 at 20:04
-
3You say C++'s inference is simplistic compared to 'grown ups', but the syntax you use to demonstrate this: `foo(1, [](auto x) { ++x; });` is already well understood and C++'s inference doesn't need any additional complexity to handle it. You can today express exactly the proposed meaning of that lambda, and C++ will handle it just fine. – bames53 Apr 22 '12 at 00:32
-
@bames53: I have not been able to compile `foo(1, [](auto& x) {++x;});`, have you ? The replacement you propose works, but it's no longer about type-inference, because you fixed the type of `lambda`. – Matthieu M. Apr 22 '12 at 11:11
-
@MatthieuM. I didn't 'fix' the type of the lambda, I simply wrote out exactly what that lambda means; and auto parameter means that the functor's `operator()` is a template function. If there's any experimental compiler that implements the auto lambda proposal then your example would work there. You're right that it's not about type inference, because clever inference isn't necessary to deal with your example. – bames53 Apr 22 '12 at 16:34