Is it simple : decltype(*std::begin(container))
is resolved in a T const &
.
Apply the same operations as val_type
, add some typename
keywords and it'll work.
Why is typename mandatory ? Look at the errors :
error: expected a type, got ‘std::remove_reference<decltype (* std::begin(container))>::type’
If you try just adding typename before this expresssion, you now have :
error: need ‘typename’ before
‘std::remove_const<typename std::remove_reference<decltype (* std::begin(container))>::type>::type’
because
‘std::remove_const<typename std::remove_reference<decltype (* std::begin(container))>::type>’
is a dependent scope
Working example with GCC 4.7.2 :
#include <iostream>
#include <type_traits>
#include <vector>
using namespace std;
template <class T>
auto sum (T const & container)
-> typename remove_const<typename remove_reference<decltype(*begin(container))>::type>::type
{
typedef typename remove_const<typename remove_reference<decltype(*begin(container))>::type>::type val_type;
val_type sum;
if (is_arithmetic<val_type>::value)
sum = 0;
for (const auto& value: container)
sum = sum + value;
return sum;
}
int main ()
{
vector<int> v { 0, 1, 2, 3 };
cout << sum(v) << endl;
}