Search code examples
c++templatesc++11static-assert

Making sure a predicate function is valid in C++ templated function


When writing a function that accepts a predicate function, such as the one below; how can you ensure the predicate function is valid (i.e. the return type of operator() is valid)?

template <typename Predicate>
std::vector<SomeType> SearchList( Predicate func ) 
{
     std::vector<SomeType> vecResults;
     for( const auto& someObj : someTypeList )
     {
          if( func( someObj ) )
              vecResults.emplace_back( someObj );
     }

     return vecResults;
}

Looking around at the type-traits facility in C++11, I've discovered std::is_convertible<From,To>, which looks like it should help, although I'm not sure how to use it to check there is a suitable implicit conversion from operator() to bool. The only things I could think of were:

static_assert( std::is_convertible<Predicate(SomeType), bool>::value, "Predicate type must be convertible to bool" );

Or:

static_assert( std::is_convertible<Predicate::operator()(SomeType), bool>::value, "Predicate type must be convertible to bool" );

But neither of these seem to look correct to me.


Solution

  • You could use:

    #include <utility> // For std::declval<>()
    
    static_assert(
        std::is_convertible<decltype(func(std::declval<SomeType>())), bool>::value,
        "Predicate's return type must be convertible to bool");
    

    If you only have the type Predicate or do not want to use func in the expression:

    static_assert(
        std::is_convertible<
            decltype(std::declval<Predicate&>()(std::declval<SomeType>())),
            bool>::value,
        "Predicate's return type must be convertible to bool");