Having the following piece of code:
#include <iostream>
#include <type_traits>
template <typename F,
typename = typename std::enable_if<
std::is_function< F >::value
>::type>
int fun( F f ) // line 8
{
return f(3);
}
int l7(int x)
{
return x%7;
}
int main()
{
auto l = [](int x) -> int{
return x%7;
};
fun(l); // line 23
//fun(l7); this will also fail even though l7 is a regular function
std::cout << std::is_function<decltype(l7)>::value ; // prints 1
}
I will get the following error:
main2.cpp: In function ‘int main()’:
main2.cpp:23:8: error: no matching function for call to ‘fun(main()::<lambda(int)>&)’
fun(l);
^
main2.cpp:8:5: note: candidate: template<class F, class> int fun(F)
int fun( F f )
^
main2.cpp:8:5: note: template argument deduction/substitution failed:
main2.cpp:5:11: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
typename = typename std::enable_if<
^
When I comment out the std::enable_if
template parameter then it compiles and runs just fine. Why?
std::is_function
only checks for function types, which doesn't include lambdas. Is there a reason you need to use SFINAE? If you really want to do the check, you could check thatf(3)
is well-formed, rather than checking iff
is function-like – Nitrosostd::is_callable
which is available with C++17, but "may be implemented in terms ofstd::is_convertible
andstd::result_of
" with pure C++11. – Olfactoryf(3)
is well formed? – Pinson