Kmat
Kmat

Reputation: 421

Template container iterators

I am working on a homework problem and I cannot get this problem to compile:

I need to write function that accepts two iterators (for any container) and return the min and max value as a pair

Here are the errors I am getting:

Error   1   error C2783: 'std::pair<T,T> problem1(It,It)' : could not deduce template argument for 'T'  
Error   2   error C2783: 'std::pair<T,T> problem1(It,It)' : could not deduce template argument for 'T'
Error   3   error C2783: 'std::pair<T,T> problem1(It,It)' : could not deduce template argument for 'T'

Here is my code:

template <typename It, typename T>
std::pair<T,T> problem1(It start, It end)
{
    // initial min max
    T min = *start;
    T max = *start;


    It curr = start;
    while (curr != end)
    {
        // check if we have a new min or max
        if (min > *curr)
            min = *curr;
        if (max < *curr)
            max = *curr;

        curr++; // get next
    }

    return std::make_pair(min, max);
}

The code is being tested with the following code, which I cannot modify.

std::vector<int> a = { 1, 3, 12, -8, 22, 5, 41, 33 };
std::list<double> b = { 0.8, -123, 44, 56, 12, 231 };
std::array<unsigned int, 1> c;
c[0] = 12;
auto a_ans = problem1(a.begin(), a.end());
auto b_ans = problem1(b.begin(), b.end());
auto c_ans = problem1(c.begin(), c.end());
if (*a_ans.first == -8 && *a_ans.second == 41 &&
    *b_ans.first == -123 && *b_ans.second == 231 &&
    *c_ans.first == 12 && *c_ans.second == 12) {
    std::cout << "Test 1 passed.\n";
    score += 10;
}
else {
    std::cout << "Test 1 failed.\n";
}

Upvotes: 1

Views: 2278

Answers (2)

zneak
zneak

Reputation: 138261

What the compiler is telling you is that it can't figure out T from the arguments that you provided to the function. Template parameters on a function either have to be explicitly provided (a_ans = problem1<vector<int>::iterator, int>(a.begin(), b.begin())), or have to be deductible from the function parameters (the compiler guesses It based on the start and end parameters).

Luckily, iterators have a value_type member:

template <typename It>
std::pair<typename It::value_type, typename It::value_type> problem1(It start, It end)
{
    // initial min max
    typename It::value_type min = *start;
    typename It::value_type max = *start;


    It curr = start;
    while (curr != end)
    {
        // check if we have a new min or max
        if (min > *curr)
            min = *curr;
        if (max < *curr)
            max = *curr;

        curr++; // get next
    }

    return std::make_pair(min, max);
}

Basically, you replace T with typename It::value_type. This works because iterator types know their value types, and this works pre-C++11 too (in case your teacher is shy about new language versions).

Upvotes: 2

Motti
Motti

Reputation: 114825

The compiler has no way to know what type T is. You can remove it from the template and use decltype(*start) instead.

The advantage of using decltype is that it will work with raw pointers and non standard iterators (unlike ::value_type)

Upvotes: 0

Related Questions