I think I understood your question, and I can think of two different approaches, both has pros and cons :
[1] Use a 3rd template type for the iterators, say ITER. Advantage is easier code, works with more collection types, less restriction. Disadvantage is, does not capture the dependency constraint between ITER and V, i.e. ITER must be an iterator which iterates over type V, namely V = ITER::value_type.
[2] Explicitly call out the dependent type instead of creating new template param. It captures the dependent types more accurately, less number of template params. Disadvantage is, it relies on the type declaration of the collection which may not be the standard (what if ITER does not have a child type ITER::value_type, or it is named differently ?) . You will use the kewyword typename for the dependent types here.
Here the compiler can do better handling of compilation errors, however note that you would hardly get any feedback about type errors unless you actually instantiate it. So you need to test the code with 2/3 concrete types.
The C++ code illustrates both approaches. BTW why are you using typename, I think it should be just "template < class V, ..". typename is used for dependent types (e.g. function accumulate2)
template <class V, class K, class ITER>
K accumulate1(
std::function<K(K, V)> accumulator,
ITER it,
ITER end,
K initial) {
K sum = initial;
for (; it != end; ++it) {
V item = *it;
sum = accumulator(sum, item);
}
return sum;
}
template <class K, class ITER>
K accumulate2(
std::function<K(K, typename ITER::value_type)> accumulator,
ITER it,
ITER end,
K initial) {
K sum = initial;
for (; it != end; ++it) {
typename ITER::value_type item = *it;
sum = accumulator(sum, item);
}
return sum;
}
string AppendInt(const string& s, int n) {
char buffer [65];
sprintf(buffer, "%s/%d", s.c_str(), n);
return string(buffer);
}
int main(int argc, char* argv[]) {
std::function<string(string,int)> fun =
[](string s, int n) -> string { return AppendInt(s,n); };
string initial = "x";
vector<int> array = {13, 24, 50, 64, 32};
string sum1 = accumulate1(fun, array.begin(), array.end(), initial);
string sum2 = accumulate2(fun, array.begin(), array.end(), initial);
printf("accumulate1 : %s\n", sum1.c_str()); // o/p: x/13/24/50/64/32
printf("accumulate2 : %s\n", sum2.c_str()); // o/p: x/13/24/50/64/32
}