As πάντα ῥεῖ says int[] decays to int*.
But this sum function is the poor man's solution, you should prefer accumulate:
cout << accumulate(numbers, next(numbers, size), decay_t<decltype(numbers[0])>{});
Live Example
If you have C++17 and a statically allocated array, such as int numbers[size], you can take advantage of cbegin and cend:
cout << accumulate(cbegin(numbers), cend(numbers), decay_t<decltype(numbers[0])>{});
I've attempted to benchmark the recursive sum against accumulate, however sum runs out of stack space before I am able to reach a vector size with a meaningful difference, making accumulate the clear winner.
I associate the type of accumulate's init agument with the type of numbers' elements: decay_t<decltype(numbers[0])>{}. The reason for this is if someone was to come back and change the type of numbers, and not change the type of accumulate's init argument the accumulation would be assigned to the wrong type.
For example if we use the accumulation line: cout << accumulate(cbegin(numbers), cend(numbers), 0), this is fine for int numbers[]. The problem would arise if we switched to define: double numbers[] = {1.3, 2.3, 3.3, 4.3}; but we failed to change the init argument we would sum doubles into an int. This would result in 10 rather than 11.2: http://ideone.com/A12xin