{
switch (__op)
{
-#if __cpp_rtti
case __get_type_info:
+#if __cpp_rtti
__dest._M_access<const type_info*>() = &typeid(_Functor);
- break;
+#else
+ __dest._M_access<const type_info*>() = nullptr;
#endif
+ break;
case __get_functor_ptr:
__dest._M_access<_Functor*>() = _M_get_pointer(__source);
break;
}
};
+ // Specialization for invalid types
+ template<>
+ class _Function_handler<void, void>
+ {
+ public:
+ static bool
+ _M_manager(_Any_data&, const _Any_data&, _Manager_operation)
+ { return false; }
+ };
+
+ // Avoids instantiating ill-formed specializations of _Function_handler
+ // in std::function<_Signature>::target<_Functor>().
+ // e.g. _Function_handler<Sig, void()> and _Function_handler<Sig, void>
+ // would be ill-formed.
+ template<typename _Signature, typename _Functor,
+ bool __valid = is_object<_Functor>::value>
+ struct _Target_handler
+ : _Function_handler<_Signature, typename remove_cv<_Functor>::type>
+ { };
+
+ template<typename _Signature, typename _Functor>
+ struct _Target_handler<_Signature, _Functor, false>
+ : _Function_handler<void, void>
+ { };
+
/**
* @brief Primary class template for std::function.
* @ingroup functors
{
_Any_data __typeinfo_result;
_M_manager(__typeinfo_result, _M_functor, __get_type_info);
- return *__typeinfo_result._M_access<const type_info*>();
+ if (auto __ti = __typeinfo_result._M_access<const type_info*>())
+ return *__ti;
}
- else
- return typeid(void);
+ return typeid(void);
}
+#endif
/**
* @brief Access the stored target function object.
*
* @return Returns a pointer to the stored target function object,
- * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL
+ * if @c typeid(_Functor).equals(target_type()); otherwise, a null
* pointer.
*
* This function does not throw exceptions.
{
const function* __const_this = this;
const _Functor* __func = __const_this->template target<_Functor>();
- return const_cast<_Functor*>(__func);
+ // If is_function_v<_Functor> is true then const_cast<_Functor*>
+ // would be ill-formed, so use *const_cast<_Functor**> instead.
+ return *const_cast<_Functor**>(&__func);
}
template<typename _Functor>
const _Functor*
target() const noexcept
{
- if (typeid(_Functor) == target_type() && _M_manager)
+ if _GLIBCXX17_CONSTEXPR (is_object<_Functor>::value)
{
- _Any_data __ptr;
- _M_manager(__ptr, _M_functor, __get_functor_ptr);
- return __ptr._M_access<const _Functor*>();
+ // For C++11 and C++14 if-constexpr is not used above, so
+ // _Target_handler avoids ill-formed _Function_handler types.
+ using _Handler = _Target_handler<_Res(_ArgTypes...), _Functor>;
+
+ if (_M_manager == &_Handler::_M_manager
+#if __cpp_rtti
+ || (_M_manager && typeid(_Functor) == target_type())
+#endif
+ )
+ {
+ _Any_data __ptr;
+ _M_manager(__ptr, _M_functor, __get_functor_ptr);
+ return __ptr._M_access<const _Functor*>();
+ }
}
- else
- return nullptr;
+ return nullptr;
}
// @}
-#endif
private:
using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
--- /dev/null
+// { dg-options "-fno-rtti" }
+// { dg-do run { target c++11 } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+using std::function;
+
+long f() { return 1; }
+struct F { long operator()() { return 2; } };
+
+void test01()
+{
+ std::function<int()> fun = f;
+ long (**tgt1)() = fun.target<long(*)()>();
+ VERIFY( *tgt1 == f );
+ VERIFY( (*tgt1)() == 1L );
+ VERIFY( fun.target<long(*)()>() == tgt1 );
+ VERIFY( fun.target<long(* const)()>() == tgt1 );
+ VERIFY( fun.target<F>() == nullptr );
+ VERIFY( fun.target<void>() == nullptr );
+ VERIFY( fun.target<int()>() == nullptr );
+ VERIFY( fun.target<long()>() == nullptr );
+
+ const F ff;
+ fun = ff;
+ F* tgt2 = fun.target<F>();
+ VERIFY( tgt2 != nullptr );
+ VERIFY( (*tgt2)() == 2L );
+ VERIFY( fun.target<const F>() == tgt2 );
+ VERIFY( fun.target<int(*)()>() == nullptr );
+ VERIFY( fun.target<void()>() == nullptr );
+ VERIFY( fun.target<void(*)()>() == nullptr );
+}
+
+int main()
+{
+ test01();
+}