https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81211
--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> --- That's not really very practical. std::function uses std::result_of to check for a callable type, and it's not an error for std::result_of to decide the type isn't callable. The error happens when std::function requests the std::result_of<>::type member, which doesn't exist. But the reason for it not existing is long gone by that point, decided earlier in the internals of std::result_of and not available to the compiler. Using decltype(std::declval<_Func&>()(std::declval<_ArgTypes>()...)) instead of result_of gives a nice diagnostic: /home/jwakely/gcc/8/include/c++/8.0.0/bits/std_function.h:465:2: note: candidate: ‘template<class _Functor, class, class> std::function<_Res(_ArgTypes ...)>::function(_Functor)’ function(_Functor); ^~~~~~~~ /home/jwakely/gcc/8/include/c++/8.0.0/bits/std_function.h:465:2: note: template argument deduction/substitution failed: /home/jwakely/gcc/8/include/c++/8.0.0/bits/std_function.h:394:55: error: use of deleted function ‘constexpr T::T(const T&)’ typename _Res2 = decltype(std::declval<_Func&>()(std::declval<_ArgTypes>()...))> ~~~~~~~~~~~~~~~~~~~~^~ func.cc:2:8: note: ‘constexpr T::T(const T&)’ is implicitly declared as deleted because ‘T’ declares a move constructor or move assignment operator struct T ^ func.cc:16:33: note: initializing argument 1 of ‘main()::<lambda(T)>’ std::function<void(T)> f{ [](T) { } }; ^ But using decltype there is incorrect, it wouldn't work for pointers to members. Which is why we use result_of. We can't add something like: static_assert( __and_<is_move_constructible<ArgTypes>...>::value, "arguments can be passed to the target function" ); Because that would reject this valid code: #include <functional> struct T { T(int) {} // uncomment one of the below to make the code compile //T(const T&) {} //T(T&& t) {} T& operator=(const T&) { return *this; } T& operator=(T&&) { return *this; } }; int main() { std::function<void(T)> f{ [](T&&) {} }; f( {1} ); } I don't see anything that can really be done to improve things here. (In reply to Stephen Kell from comment #3) > It'd be nice if I didn't have to guess that the reason it's not callable is > that I omitted the copy constructor. The rules for when constructors are > defaulted/deleted are baroque enough to catch anybody out from time to time. Not if you follow the rule of five: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all Your class has user-provided assignment operators and fails to declare copy and move constructors. Define them (maybe as =default) and there's no problem.