In modern C++, the typical way to write a fully generic algorithm is to implement the algorithm as a template. We're still going to implement the function template in terms of the public member functions .size() and .at(), but we're no longer going to require that the argument arr be of any particular type. Because our new function will be a template, we'll be telling the compiler "I don't care what type arr is. Whatever type it is, just generate a brand-new function (that is, a template instantiation) with that type as its parameter type."
template<class ContainerModel> void double_each_element(ContainerModel& arr) { for (int i=0; i < arr.size(); ++i) { arr.at(i) *= 2; } } void test() { array_of_ints arr; ...