Constructor: template<class F> function(F f);
C ++ 11:
f must be Callable for argument types ArgTypes and return type R
C ++ 14:
Do not participate in overload resolution if f does not match Callable for argument types ArgTypes... and returns type R
In C ++ 11, this constructor pattern is a better match than a transform sequence that includes the std::function move constructor and your custom transform operator. Thus, overload resolution selects a constructor template, which then does not compile because f not Callable .
In C ++ 14, the constructor pattern is prone to change replacements, since f not Callable . Thus, the constructor template is not involved in overload resolution, and the best remaining match is the conversion sequence, including the std::function move constructor and your custom transform operator, which is therefore used.
Clang compiles your test file in both C ++ 11 and C ++ 14. GCC rejects your test in both C ++ 11 and C ++ 14. Here is another test case that demonstrates the same problem in GCC :
#include <type_traits> struct A { void operator()() const {} }; struct B { void operator()() const {} }; struct C : A, B {}; template <typename F, typename = std::result_of_t<F&()>> void test(int) {} template <typename F> void test(double) {} int main() { test<C>(42); }
test(int) should not be involved in overload resolution, because std::result_of_t<F&()> should be a replacement change, so test(double) should be called. However, this code does not compile in GCC.
This is the same problem as in your test case because it is the same mechanism used to implement SFINAE in the std::function constructor std::function in libstdC ++.
source share