c++ STL algo remove_if used with template

1.1k Views Asked by At

I tried to apply stl algorithm remove_if on template, and met some trouble. Any help is appreciated!

template <class T> bool flag_delete(pair<T,int> a) {return (a.second == 1);}

template <class T> void fun_delete_by_flag(vector<T> &vec_data, ivec &vec_flag)
{
    int n = vec_data.size();
    vector< pair<T,int> > vec;
    vec.resize(n);
    for ( int i = 0; i < n; i += 1 ) {
        vec[i].first = vec_data[i];
        vec[i].second = vec_flag[i];
    }
    typename vector< pair<T,int> >::iterator it;
    it = remove_if(vec.begin(), vec.end(), flag_delete);
    n = vec.size();
    vec_data.resize(n);
    for ( int i = 0; i < n; i += 1 ) {
        vec_data[i] = vec[i].first;
    }
    return;
}

I got the below message:

guess_algo.h: In function ‘void fun_delete_by_flag(std::vector<T>&, ivec&) [with T = std::pair<int, std::basic_string<char> >, ivec = std::vector<int>]’:
user_time.h:63:34:   instantiated from here
guess_algo.h:61:2: error: no matching function for call to ‘remove_if(std::vector<std::pair<std::pair<int, std::basic_string<char> >, int>, std::allocator<std::pair<std::pair<int, std::basic_string<char> >, int> > >::iterator, std::vector<std::pair<std::pair<int, std::basic_string<char> >, int>, std::allocator<std::pair<std::pair<int, std::basic_string<char> >, int> > >::iterator, <unresolved overloaded function type>)’
3

There are 3 best solutions below

0
On

You need to change your invocation of remove_if as follows:

it = remove_if(vec.begin(), vec.end(), flag_delete<T>);

ie. add the <T> on the end of flag_delete, because you have not told it that the function should have the same template parameter as that given to fun_delete_by_flag. The hint here is the (fairly well hidden) <unresolved overloaded function type> on the end of the error message.

0
On

Try to look at first line of the error messages:

guess_algo.h: In function ‘void fun_delete_by_flag(std::vector<T>&, ivec&) [with T = std::pair<int, std::basic_string<char> >, ivec = std::vector<int>]’:

That tells you that T is type pair. And last line tells you (at the end) you are calling "unresolved overloaded function type". That means, you are giving it different parameters than are defined in function flag_delete.

From firs error message, you are giving it pair . Try to check your types, and, maybe, change T to another character.

0
On

Regardless of the points made by others (need to specificy template parameter), you are missing the call to std::vector::erase (or the vec_data.resize() call is redundant).

std::remove_if does not reduce the container's size!

So, either add the marked line

auto it = remove_if(vec.begin(), vec.end(), flag_delete<T>);
vec.erase(it);        // <-- ADD THIS TO ACTUALLY REDUCE CONTAINER LENGTH
n = vec.size();
vec_data.resize(n);

Or rewrite it a bit. Knowing that vector allocation is contiguous as per the standard, you could condense the whole of it to (assuming c++0x support):

template <class T> void simpler(vector<T> &vec_data, const ivec &vec_flag)
{
    T *begin = &vec_data.front();
    size_t newsize = std::distance(begin, 
            std::remove_if(
                begin, begin + vec_data.size(), [&] (T& el) 
                { 
                    return 1 == vec_flag[std::distance(begin, &el)]; 
                }));

    vec_data.resize(newsize);
}

See it live: http://ideone.com/S2WUC

Edit I have cleaned the original function up a bit too (note const&, size_t, erase, reserve and std::make_pair):

template <class T> void fun_delete_by_flag(vector<T> &vec_data, const ivec &vec_flag)
{
    size_t n = vec_data.size();
    vector< pair<T,int> > vec;
    vec.reserve(n);
    for ( size_t i = 0; i < n; i += 1 ) 
        vec.push_back(std::make_pair(vec_data[i], vec_flag[i]));

    vec.erase(remove_if(vec.begin(), vec.end(), flag_delete<T>));

    n = vec.size();
    vec_data.resize(n);

    for ( size_t i = 0; i < n; i += 1 )
        vec_data[i] = vec[i].first;

    return;
}