1

I came up with my own little class called TinyVector. And now I'm trying to use std::inner_product on it. But I can't get it to work and I don't understand why this does not work. I'm using Visual Studio 2012.

#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

template<class T, int N>
class TinyVector {
public:
    TinyVector() { data = vector<T>(N, 0); }
    explicit TinyVector(const T initVal) { data = vector<T>(N, initVal); }
    ~TinyVector() { data.clear(); }
    inline T& operator[](int i) { return data[i]; }
    inline T operator[](int i) const { return data[i]; }
    inline vector<T>::const_iterator begin() const { return data.begin(); } //Line 15
    inline vector<T>::const_iterator end() const { return data.end(); } //Line 16
private:
    vector<T> data;
};

template<class T, int N>
inline double dot(const TinyVector<T,N>& A, const TinyVector<T,N>&  B)
{
    return inner_product(A.begin(), A.end(), B.begin(), 0.0);
}

int main()
{
    TinyVector<double, 10> Ty;
    for (int i = 0; i < 10; ++i)
        Ty[i] = i;

    cout << dot(Ty,Ty) << endl;
}

The compiler tells me: syntax error : missing ';' before identifier 'begin' on line 15. missing type specifier - int assumed. Note: C++ does not support default-int on line 15. syntax error : missing ';' before identifier 'end' on line 16. missing type specifier - int assumed. Note: C++ does not support default-int on line 16.

But changing vector<T>::const_iterator into vector::const_iterator doesn't seem like the way to go. Also changing it to 'auto' does not work. This gives me "expected a trailing return type". If I delete line 15,16 and 17 and replace A.begin() with A.data.begin() and the next two arguments accoringly, everything is fine. But why doesn't my original code work, and how can I get it to work?

Dominic Hofer
  • 5,751
  • 4
  • 18
  • 23

1 Answers1

5

You need to write

inline typename vector<T>::const_iterator begin() const { return data.begin(); } //Line 15
       ^^^^^^^^

This is because vector<T>::const_iterator is a dependent name (it is dependent on the type parameter T) and so the compiler needs to be told that vector<T>::const_iterator is a type (and not, say, an enum value or static data member).

Dominic Hofer
  • 5,751
  • 4
  • 18
  • 23
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Wow, it really is that simple. So you are trying to say me, that whenever I use a type that is depending on a template value, I have to use 'typename' to tell the compiler my type is a type? Because otherwise the compiler must assume the instantiation of this templated "type" could be something else? – Dominic Hofer Oct 19 '12 at 12:23
  • @PanicSheep for any `typedef` members, yes (you don't need it when you write `vector`, for example). A good rule of thumb is wherever you see `::` you probably need to use `typename`. See [Where and why do I have to put the “template” and “typename” keywords?](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) for a more in depth explanation. – ecatmur Oct 19 '12 at 14:15