Question

So, defining a predicate inside a function and use as std::list::remove_if argument is not allowed?


Consider the following code, which fails to compile:

struct a { };

int main()
{
    struct pred { bool operator()( const a& ) { return false; }  };

    std::list< a > l; // fill l
    l.remove_if( pred() );

    return 0;
}

error: no matching function for call to 
    ‘std::list<a, std::allocator<a> >::remove_if(main()::pred)’

Now, if I replace l.remove_if( pred() ); with

pred()( *l.begin() );
// or
pred p;
p( *l.begin() );

which remove_if does internally, it compiles and works as expected.

And even more: if I move struct pred to be defined outside main, both tests work as expected.


This doesn't make any sense to me.

I thought that it could be something with dependent names and ADL and things like this, but... the argument of remove_if is an instance, not a type. It's true, that this is a template function and the argument's type is still resolved, but..

Can somebody explain what and why happens?

Was it helpful?

Solution

The answer to your very first question is that yes, prior to C++11 some types (such as local types) are NOT allowed as template parameters. See 14.3.1/2:

A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template argument for a template type parameter.

Since remove_if is a template, you cannot use the local predicate as its parameter.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top