0

I want to determine if the element in vector is average between its neighbours so I wrote this program

#include <iostream>
#include <vector>
using namespace std;

template <typename T>
bool is_avg(vector<T>::iterator x) {         <-- error line
    T l = *(x - 1), m = *x, r = *(x + 1);
    return x * 2 == l + r;
}

int main() {
    vector<int> v;
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    cout << (is_avg(v.begin() + 1) ? "Yes" : "No");
    return 0;
}

But it doesn't work

main.cpp|6|error: template declaration of 'bool is_avg'

What is wrong?

Pavel
  • 5,374
  • 4
  • 30
  • 55

1 Answers1

1

Two things: first, you shoudl use m * 2 instead of x * 2, and you cannot deduce T from vector<T>::iterator. Instead, use It as a template parameter:

#include <iostream>
#include <vector>
using namespace std;

template <typename It>
bool is_avg(It x) {        // <-- error line
    auto const& l = *(x - 1), m = *x, r = *(x + 1);
    return m * 2 == l + r;
}

int main() {
    vector<int> v;
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    cout << (is_avg(v.begin() + 1) ? "Yes" : "No");
}

Live Example

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • Thank you. (`x * 2` is an accidentally error). Can you explain why it is not possible to deduce `T` from `vector::iterator`? Can I create a variable with type `T` without using `auto` (for example in C++98)? – Pavel Sep 01 '16 at 17:38
  • 1
    @Pavel essentially (for details, see the duplicate Q&A), the compiler has to match the pattern `vector::iterator` against the argument passed, but while doing so, it can only look at the general form of the pattern, and not "inside it". Another phrase people use is that compilers can't see beyond a `::`, which is why the `iterator` is not matched. – TemplateRex Sep 01 '16 at 17:42