Index: include/functional =================================================================== --- include/functional +++ include/functional @@ -2335,6 +2335,97 @@ #endif // _LIBCPP_NO_RTTI }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template +struct __function_ctad; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...)> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) volatile> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) volatile noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const volatile> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const volatile noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) &> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) & noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const &> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const & noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) volatile &> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) volatile & noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const volatile &> { + using type = _Rp(_ArgTypes...); +}; + +template +struct __function_ctad<_Tp, _Rp(_Gp::*)(_ArgTypes...) const volatile & noexcept> { + using type = _Rp(_ArgTypes...); +}; + +template +function(_Rp(*)(_ArgTypes...)) -> function<_Rp(_ArgTypes...)>; + +template::type> +function(_Tp) -> function<_Sig>; +#endif + template function<_Rp(_ArgTypes...)>::function(const function& __f) : __f_(__f.__f_) {} Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct.fail.cpp =================================================================== --- /dev/null +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct.fail.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class function + +// function(F); + +#include + +#include "test_macros.h" + +struct A { + int operator()(int) const { return 2; } + int foo(int) const { return 1; } +}; + +struct Callable { + template + void operator()(Args...) const {} +}; + +int g(int) { return 0; } + +int main(int, char**) +{ + { + std::function f = nullptr; + //expected-error@-1{{no viable constructor or deduction guide}} + } + { + std::function f = &A::foo; + //expected-error@-1{{no viable constructor or deduction guide}} + } + { + std::function f = Callable(); + //expected-error@-1{{no viable constructor or deduction guide}} + } + { + A a; + std::function f = std::ref(a); + //expected-error@-1{{no viable constructor or deduction guide}} + } + + return 0; +} Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/deduct.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class function + +// function(F); + +#include + +#include "test_macros.h" + +struct A { + static void foo() {} + int operator()(int i) const { + return i; + } +}; + +union B { + int data; + int operator()(int i) const { + return i; + } +}; + +struct LValueCallable { + void operator()() & {} +}; + +int gfunc(int) { return 0; } + +int gfunc_default(int i = 42) { return i; } + +int gfunc_noexcept(int) noexcept { return 0; } + +int main(int, char**) +{ + { + // [func.wrap.func.con]/13 + int i = 5; + std::function g = [&](double) { return i; }; + ASSERT_SAME_TYPE(decltype(g), std::function); + } + { + std::function f = gfunc; + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f = gfunc_default; + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f = gfunc_noexcept; + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f = &A::foo; + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f = (int (*)(int))0; + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f(&gfunc); + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f = A(); + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f = B(); + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function f = LValueCallable(); + ASSERT_SAME_TYPE(decltype(f), std::function); + } + { + std::function a; + std::function b(a); + ASSERT_SAME_TYPE(decltype(b), std::function); + } + { + const std::function a; + std::function b(a); + ASSERT_SAME_TYPE(decltype(b), std::function); + } + { + std::function a; + std::function b = a; + ASSERT_SAME_TYPE(decltype(b), std::function); + } + + { + std::function a; + std::function b = a; + ASSERT_SAME_TYPE(decltype(b), std::function); + } + + { + std::function a; + std::function b(std::move(a)); + ASSERT_SAME_TYPE(decltype(b), std::function); + } + + { + const std::function a; + std::function b(std::move(a)); + ASSERT_SAME_TYPE(decltype(b), std::function); + } + + { + std::function a; + std::function b(std::move(a)); + ASSERT_SAME_TYPE(decltype(b), std::function); + } + + { + std::function a; + std::function b = std::move(a); + ASSERT_SAME_TYPE(decltype(b), std::function); + } + + return 0; +}