Index: include/__functional_03 =================================================================== --- include/__functional_03 +++ include/__functional_03 @@ -369,7 +369,8 @@ _Rp __func<_Fp, _Alloc, _Rp()>::operator()() { - return __invoke(__f_.first()); + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first()); } #ifndef _LIBCPP_NO_RTTI @@ -452,7 +453,8 @@ _Rp __func<_Fp, _Alloc, _Rp(_A0)>::operator()(_A0 __a0) { - return __invoke(__f_.first(), __a0); + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), __a0); } #ifndef _LIBCPP_NO_RTTI @@ -535,7 +537,8 @@ _Rp __func<_Fp, _Alloc, _Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) { - return __invoke(__f_.first(), __a0, __a1); + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), __a0, __a1); } #ifndef _LIBCPP_NO_RTTI @@ -618,7 +621,8 @@ _Rp __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) { - return __invoke(__f_.first(), __a0, __a1, __a2); + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), __a0, __a1, __a2); } #ifndef _LIBCPP_NO_RTTI Index: include/__functional_base =================================================================== --- include/__functional_base +++ include/__functional_base @@ -419,6 +419,26 @@ typedef decltype(__invoke(_VSTD::declval<_Tp>(), _VSTD::declval<_Args>()...)) type; }; +template +struct __invoke_void_return_wrapper +{ + template + static _Ret __call(_Args&&... __args) + { + return __invoke(_VSTD::forward<_Args>(__args)...); + } +}; + +template <> +struct __invoke_void_return_wrapper +{ + template + static void __call(_Args&&... __args) + { + __invoke(_VSTD::forward<_Args>(__args)...); + } +}; + template class _LIBCPP_TYPE_VIS_ONLY reference_wrapper : public __weak_result_type<_Tp> Index: include/__functional_base_03 =================================================================== --- include/__functional_base_03 +++ include/__functional_base_03 @@ -995,6 +995,63 @@ _VSTD::declval<_A2>())) type; }; +template +struct __invoke_void_return_wrapper +{ + template + static _Ret __call(_Fn __f) + { + return __invoke(__f); + } + + template + static _Ret __call(_Fn __f, _A0& __a0) + { + return __invoke(__f, __a0); + } + + template + static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) + { + return __invoke(__f, __a0, __a1); + } + + template + static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) + { + return __invoke(__f, __a0, __a1, __a2); + } +}; + + +template <> +struct __invoke_void_return_wrapper +{ + template + static void __call(_Fn __f) + { + __invoke(__f); + } + + template + static void __call(_Fn __f, _A0& __a0) + { + __invoke(__f, __a0); + } + + template + static void __call(_Fn __f, _A0& __a0, _A1& __a1) + { + __invoke(__f, __a0, __a1); + } + + template + static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) + { + __invoke(__f, __a0, __a1, __a2); + } +}; + template class _LIBCPP_TYPE_VIS_ONLY reference_wrapper : public __weak_result_type<_Tp> Index: include/functional =================================================================== --- include/functional +++ include/functional @@ -1367,7 +1367,8 @@ _Rp __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) { - return __invoke(__f_.first(), _VSTD::forward<_ArgTypes>(__arg)...); + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), _VSTD::forward<_ArgTypes>(__arg)...); } #ifndef _LIBCPP_NO_RTTI @@ -1429,7 +1430,7 @@ template struct __callable<_Fp, true> { - static const bool value = + static const bool value = is_same::value || is_convertible::type, _Rp>::value; }; Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp =================================================================== --- test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp @@ -81,4 +81,10 @@ assert(globalMemCounter.checkOutstandingNewEq(0)); assert(f.target() != 0); } + { + std::function f(&g); + assert(f); + assert(f.target() != 0); + f(1); + } } Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp =================================================================== --- test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_assign.pass.cpp @@ -88,4 +88,11 @@ assert(globalMemCounter.checkOutstandingNewEq(0)); assert(f.target() != 0); } + { + std::function f; + f = &g; + assert(f); + assert(f.target() != 0); + f(1); + } } Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp =================================================================== --- test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp @@ -87,4 +87,12 @@ std::function fun = std::bind(&Foo::bar, &f, std::placeholders::_1); fun(10); } + { + std::function fun(std::allocator_arg, + test_allocator(), + &g); + assert(fun); + assert(fun.target() != 0); + fun(10); + } } Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.inv/invoke_no_variadics.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.inv/invoke_no_variadics.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// class function + +// Test that we properly return both values and void for all non-variadic +// overloads of function::operator()(...) + +#define _LIBCPP_HAS_NO_VARIADICS +#include +#include + +int foo0() { return 42; } +int foo1(int) { return 42; } +int foo2(int, int) { return 42; } +int foo3(int, int, int) { return 42; } + +int main() +{ + { + std::function f(&foo0); + assert(f() == 42); + } + { + std::function f(&foo1); + assert(f(1) == 42); + } + { + std::function f(&foo2); + assert(f(1, 1) == 42); + } + { + std::function f(&foo3); + assert(f(1, 1, 1) == 42); + } + { + std::function f(&foo0); + f(); + } + { + std::function f(&foo1); + f(1); + } + { + std::function f(&foo2); + f(1, 1); + } + { + std::function f(&foo3); + f(1, 1, 1); + } +}