diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h --- a/llvm/include/llvm/ADT/FunctionExtras.h +++ b/llvm/include/llvm/ADT/FunctionExtras.h @@ -59,6 +59,15 @@ using EnableIfTrivial = std::enable_if_t::value && std::is_trivially_destructible::value>; +template +using EnableUnlessSameType = std::enable_if_t>, ThisT>::value>; +template +using EnableIfCallable = + std::enable_if_t::value || + std::is_convertible()( + std::declval()...)), + Ret>::value>; template class UniqueFunctionBase { protected: @@ -346,7 +355,10 @@ unique_function &operator=(const unique_function &) = delete; template - unique_function(CallableT Callable) + unique_function( + CallableT Callable, + detail::EnableUnlessSameType * = nullptr, + detail::EnableIfCallable * = nullptr) : Base(std::forward(Callable), typename Base::template CalledAs{}) {} @@ -369,7 +381,10 @@ unique_function &operator=(const unique_function &) = delete; template - unique_function(CallableT Callable) + unique_function( + CallableT Callable, + detail::EnableUnlessSameType * = nullptr, + detail::EnableIfCallable * = nullptr) : Base(std::forward(Callable), typename Base::template CalledAs{}) {} diff --git a/llvm/unittests/ADT/FunctionExtrasTest.cpp b/llvm/unittests/ADT/FunctionExtrasTest.cpp --- a/llvm/unittests/ADT/FunctionExtrasTest.cpp +++ b/llvm/unittests/ADT/FunctionExtrasTest.cpp @@ -262,4 +262,15 @@ EXPECT_EQ("const", X()); } +// Test that overloads on unique_functions are resolved as expected. +std::string returns(StringRef) { return "not a function"; } +std::string returns(function_ref F) { return "number"; } +std::string returns(function_ref F) { return "string"; } + +TEST(FunctionRefTest, SFINAE) { + EXPECT_EQ("not a function", returns("boo!")); + EXPECT_EQ("number", returns([] { return 42; })); + EXPECT_EQ("string", returns([] { return "hello"; })); +} + } // anonymous namespace