For initialization, we need the neutral element of the value type wrt. addition, which can be deduced via a typ map. This permits to implement a convenience version of sum without explicit init parameter.

## Computing the neutral element

For those cases with a unique neutral element (wrt. addition) we can offer a simplification which does not need `init` any more. To implement this, we need to deduce, in addition to the value type, also the value of the neutral element from `Iterator`. In analogy to `value_type` we can define a type mapping `neutral_element_addition`, which now does not map type to type but type to value. It is also more natural to define this map directly on the value type instead of the iterator type. As normally, the neutral element can be initialized with the literal 0, we use this as default definition in the primary template.

```template<typename T>
{ static T value() { return T(0); } };

template<>
{ static std::string value() { return std::string(""); } };
```

In the example above, only for `std::string` an exception (via template specialization) was defined. For your own, blazingly fast 3D vector class `vec3` you have to implement a similar specialization, if `vec3(0)` does not work:

```template<>
{ static vec3 value() { return vec3(0.0,0.0,0.0); } };
```

### Sum with automatic init

In the new implementation of `sum2` we now get the neutral element via `neutral_element_addition`, spending a `typedef` for clarity:

```template<typename Iterator>
typename value_type<Iterator>::result
sum2b(Iterator  a, Iterator a_end)
{
typedef typename value_type<Iterator>::result value_t;
for(; a != a_end; ++a)
res += *a;
return res;
}
```

We can offer this comfortable overload alongside the general version with explicit init. So, finally our examples for `string` and `float` work without any tweaks at the calling site:

```float a[] = { 0.0, 0.5, 1.0, 1.5 };
float suma = sum2b(a, a+4); // beware of long sequences!

std::string words[] = { "This", "is", "a", "sentence" };
std::string sentence = sum2b(words, words+4);
```

#### Narrow value types hit again

... just the output for strings is not as pleasant. And an old problem is striking back: Automatic computation of the init argument makes it more likely to fall into the trap of a too narrow value type:

```vector<unsigned char> dice_rolls(BigN);

// surprise: unsigned char used for summing
unsigned sum_dice_rolls = sum2b(dice_rolls.begin(), dice_rolls.end());
```

When only the version (`sum3`) with explicit `init` parameter is available, there is at least a visible, explicit mention of that inadequate type at the calling site (and a chance of the programmer choosing a better type for `init`). It is a good excercise to think about if and how this could be resolved (and you'll leave the scope of this tutorial when doing so).