[libc++] Remove some workarounds for missing variadic templates

We don't support GCC in C++03 mode, and Clang provides variadic templates
even in C++03 mode. So there's effectively no supported compiler that
doesn't support variadic templates.

This effectively gets rid of all uses of _LIBCPP_HAS_NO_VARIADICS, but
some workarounds for the lack of variadics remain.
This commit is contained in:
Louis Dionne 2020-07-30 10:00:53 -04:00
parent c3492a1aa1
commit a3c28ccd49
5 changed files with 92 additions and 396 deletions

View File

@ -456,10 +456,6 @@ typedef __char32_t char32_t;
#define _LIBCPP_HAS_NO_AUTO_TYPE
#endif
#if !(__has_feature(cxx_variadic_templates))
#define _LIBCPP_HAS_NO_VARIADICS
#endif
// Objective-C++ features (opt-in)
#if __has_feature(objc_arc)
#define _LIBCPP_HAS_OBJC_ARC

View File

@ -1605,8 +1605,6 @@ template <class _Rp, class _Alloc>
struct _LIBCPP_TEMPLATE_VIS uses_allocator<promise<_Rp>, _Alloc>
: public true_type {};
#ifndef _LIBCPP_HAS_NO_VARIADICS
// packaged_task
template<class _Fp> class __packaged_task_base;
@ -2158,6 +2156,8 @@ __make_async_assoc_state(_Fp&& __f)
return future<_Rp>(__h.get());
}
#ifndef _LIBCPP_CXX03_LANG
template <class _Fp, class... _Args>
class _LIBCPP_HIDDEN __async_func
{
@ -2225,7 +2225,7 @@ async(_Fp&& __f, _Args&&... __args)
_VSTD::forward<_Args>(__args)...);
}
#endif // _LIBCPP_HAS_NO_VARIADICS
#endif // C++03
// shared_future

View File

@ -762,8 +762,6 @@ struct __pointer_traits_element_type<_Ptr, true>
typedef _LIBCPP_NODEBUG_TYPE typename _Ptr::element_type type;
};
#ifndef _LIBCPP_HAS_NO_VARIADICS
template <template <class, class...> class _Sp, class _Tp, class ..._Args>
struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true>
{
@ -776,60 +774,6 @@ struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false>
typedef _LIBCPP_NODEBUG_TYPE _Tp type;
};
#else // _LIBCPP_HAS_NO_VARIADICS
template <template <class> class _Sp, class _Tp>
struct __pointer_traits_element_type<_Sp<_Tp>, true>
{
typedef typename _Sp<_Tp>::element_type type;
};
template <template <class> class _Sp, class _Tp>
struct __pointer_traits_element_type<_Sp<_Tp>, false>
{
typedef _Tp type;
};
template <template <class, class> class _Sp, class _Tp, class _A0>
struct __pointer_traits_element_type<_Sp<_Tp, _A0>, true>
{
typedef typename _Sp<_Tp, _A0>::element_type type;
};
template <template <class, class> class _Sp, class _Tp, class _A0>
struct __pointer_traits_element_type<_Sp<_Tp, _A0>, false>
{
typedef _Tp type;
};
template <template <class, class, class> class _Sp, class _Tp, class _A0, class _A1>
struct __pointer_traits_element_type<_Sp<_Tp, _A0, _A1>, true>
{
typedef typename _Sp<_Tp, _A0, _A1>::element_type type;
};
template <template <class, class, class> class _Sp, class _Tp, class _A0, class _A1>
struct __pointer_traits_element_type<_Sp<_Tp, _A0, _A1>, false>
{
typedef _Tp type;
};
template <template <class, class, class, class> class _Sp, class _Tp, class _A0,
class _A1, class _A2>
struct __pointer_traits_element_type<_Sp<_Tp, _A0, _A1, _A2>, true>
{
typedef typename _Sp<_Tp, _A0, _A1, _A2>::element_type type;
};
template <template <class, class, class, class> class _Sp, class _Tp, class _A0,
class _A1, class _A2>
struct __pointer_traits_element_type<_Sp<_Tp, _A0, _A1, _A2>, false>
{
typedef _Tp type;
};
#endif // _LIBCPP_HAS_NO_VARIADICS
template <class _Tp, class = void>
struct __has_difference_type : false_type {};
@ -872,8 +816,6 @@ struct __pointer_traits_rebind
#endif
};
#ifndef _LIBCPP_HAS_NO_VARIADICS
template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true>
{
@ -890,78 +832,6 @@ struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false>
typedef _Sp<_Up, _Args...> type;
};
#else // _LIBCPP_HAS_NO_VARIADICS
template <template <class> class _Sp, class _Tp, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp>, _Up, true>
{
#ifndef _LIBCPP_CXX03_LANG
typedef typename _Sp<_Tp>::template rebind<_Up> type;
#else
typedef typename _Sp<_Tp>::template rebind<_Up>::other type;
#endif
};
template <template <class> class _Sp, class _Tp, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp>, _Up, false>
{
typedef _Sp<_Up> type;
};
template <template <class, class> class _Sp, class _Tp, class _A0, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp, _A0>, _Up, true>
{
#ifndef _LIBCPP_CXX03_LANG
typedef typename _Sp<_Tp, _A0>::template rebind<_Up> type;
#else
typedef typename _Sp<_Tp, _A0>::template rebind<_Up>::other type;
#endif
};
template <template <class, class> class _Sp, class _Tp, class _A0, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp, _A0>, _Up, false>
{
typedef _Sp<_Up, _A0> type;
};
template <template <class, class, class> class _Sp, class _Tp, class _A0,
class _A1, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp, _A0, _A1>, _Up, true>
{
#ifndef _LIBCPP_CXX03_LANG
typedef typename _Sp<_Tp, _A0, _A1>::template rebind<_Up> type;
#else
typedef typename _Sp<_Tp, _A0, _A1>::template rebind<_Up>::other type;
#endif
};
template <template <class, class, class> class _Sp, class _Tp, class _A0,
class _A1, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp, _A0, _A1>, _Up, false>
{
typedef _Sp<_Up, _A0, _A1> type;
};
template <template <class, class, class, class> class _Sp, class _Tp, class _A0,
class _A1, class _A2, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp, _A0, _A1, _A2>, _Up, true>
{
#ifndef _LIBCPP_CXX03_LANG
typedef typename _Sp<_Tp, _A0, _A1, _A2>::template rebind<_Up> type;
#else
typedef typename _Sp<_Tp, _A0, _A1, _A2>::template rebind<_Up>::other type;
#endif
};
template <template <class, class, class, class> class _Sp, class _Tp, class _A0,
class _A1, class _A2, class _Up>
struct __pointer_traits_rebind<_Sp<_Tp, _A0, _A1, _A2>, _Up, false>
{
typedef _Sp<_Up, _A0, _A1, _A2> type;
};
#endif // _LIBCPP_HAS_NO_VARIADICS
template <class _Ptr>
struct _LIBCPP_TEMPLATE_VIS pointer_traits
{
@ -3415,31 +3285,18 @@ public:
__shared_ptr_emplace(_Alloc __a)
: __data_(_VSTD::move(__a), __value_init_tag()) {}
#ifndef _LIBCPP_HAS_NO_VARIADICS
#ifndef _LIBCPP_CXX03_LANG
template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY
__shared_ptr_emplace(_Alloc __a, _Args&& ...__args)
: __data_(piecewise_construct, _VSTD::forward_as_tuple(__a),
_VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)) {}
#else // _LIBCPP_HAS_NO_VARIADICS
template <class _A0>
#else
template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY
__shared_ptr_emplace(_Alloc __a, _A0& __a0)
: __data_(__a, _Tp(__a0)) {}
template <class _A0, class _A1>
_LIBCPP_INLINE_VISIBILITY
__shared_ptr_emplace(_Alloc __a, _A0& __a0, _A1& __a1)
: __data_(__a, _Tp(__a0, __a1)) {}
template <class _A0, class _A1, class _A2>
_LIBCPP_INLINE_VISIBILITY
__shared_ptr_emplace(_Alloc __a, _A0& __a0, _A1& __a1, _A2& __a2)
: __data_(__a, _Tp(__a0, __a1, __a2)) {}
#endif // _LIBCPP_HAS_NO_VARIADICS
__shared_ptr_emplace(_Alloc __a, _Args&& ...__args)
: __data_(__a, _Tp(_VSTD::forward<_Args>(__args)...)) {}
#endif
private:
virtual void __on_zero_shared() _NOEXCEPT;
@ -5041,7 +4898,6 @@ struct __noexcept_move_assign_container : public integral_constant<bool,
> {};
#ifndef _LIBCPP_HAS_NO_VARIADICS
template <class _Tp, class _Alloc>
struct __temp_value {
typedef allocator_traits<_Alloc> _Traits;
@ -5061,7 +4917,6 @@ struct __temp_value {
~__temp_value() { _Traits::destroy(__a, __addr()); }
};
#endif
template<typename _Alloc, typename = void, typename = void>
struct __is_allocator : false_type {};

View File

@ -2876,158 +2876,6 @@ struct __member_pointer_class_type<_Ret _ClassType::*> {
typedef _ClassType type;
};
// result_of
template <class _Callable> class result_of;
#ifdef _LIBCPP_HAS_NO_VARIADICS
template <class _Fn, bool, bool>
class __result_of
{
};
template <class _Fn>
class __result_of<_Fn(), true, false>
{
public:
typedef decltype(declval<_Fn>()()) type;
};
template <class _Fn, class _A0>
class __result_of<_Fn(_A0), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_A0>())) type;
};
template <class _Fn, class _A0, class _A1>
class __result_of<_Fn(_A0, _A1), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_A0>(), declval<_A1>())) type;
};
template <class _Fn, class _A0, class _A1, class _A2>
class __result_of<_Fn(_A0, _A1, _A2), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_A0>(), declval<_A1>(), declval<_A2>())) type;
};
template <class _MP, class _Tp, bool _IsMemberFunctionPtr>
struct __result_of_mp;
// member function pointer
template <class _MP, class _Tp>
struct __result_of_mp<_MP, _Tp, true>
: public __identity<typename __member_pointer_traits<_MP>::_ReturnType>
{
};
// member data pointer
template <class _MP, class _Tp, bool>
struct __result_of_mdp;
template <class _Rp, class _Class, class _Tp>
struct __result_of_mdp<_Rp _Class::*, _Tp, false>
{
typedef typename __apply_cv<decltype(*_VSTD::declval<_Tp>()), _Rp>::type& type;
};
template <class _Rp, class _Class, class _Tp>
struct __result_of_mdp<_Rp _Class::*, _Tp, true>
{
typedef typename __apply_cv<_Tp, _Rp>::type& type;
};
template <class _Rp, class _Class, class _Tp>
struct __result_of_mp<_Rp _Class::*, _Tp, false>
: public __result_of_mdp<_Rp _Class::*, _Tp,
is_base_of<_Class, typename remove_reference<_Tp>::type>::value>
{
};
template <class _Fn, class _Tp>
class __result_of<_Fn(_Tp), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class _Tp, class _A0>
class __result_of<_Fn(_Tp, _A0), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class _Tp, class _A0, class _A1>
class __result_of<_Fn(_Tp, _A0, _A1), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class _Tp, class _A0, class _A1, class _A2>
class __result_of<_Fn(_Tp, _A0, _A1, _A2), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
// result_of
template <class _Fn>
class _LIBCPP_TEMPLATE_VIS result_of<_Fn()>
: public __result_of<_Fn(),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<typename remove_reference<_Fn>::type>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
template <class _Fn, class _A0>
class _LIBCPP_TEMPLATE_VIS result_of<_Fn(_A0)>
: public __result_of<_Fn(_A0),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<typename remove_reference<_Fn>::type>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
template <class _Fn, class _A0, class _A1>
class _LIBCPP_TEMPLATE_VIS result_of<_Fn(_A0, _A1)>
: public __result_of<_Fn(_A0, _A1),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<typename remove_reference<_Fn>::type>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
template <class _Fn, class _A0, class _A1, class _A2>
class _LIBCPP_TEMPLATE_VIS result_of<_Fn(_A0, _A1, _A2)>
: public __result_of<_Fn(_A0, _A1, _A2),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<typename remove_reference<_Fn>::type>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
#endif // _LIBCPP_HAS_NO_VARIADICS
// template <class T, class... Args> struct is_constructible;
namespace __is_construct
@ -3982,14 +3830,97 @@ struct __invoke_of
{
};
#endif // _LIBCPP_CXX03_LANG
// result_of
template <class _Callable> class result_of;
#ifndef _LIBCPP_CXX03_LANG
template <class _Fp, class ..._Args>
class _LIBCPP_TEMPLATE_VIS result_of<_Fp(_Args...)>
: public __invoke_of<_Fp, _Args...>
{
};
#else // C++03
template <class _Fn, bool, bool>
class __result_of
{
};
template <class _Fn, class ..._Args>
class __result_of<_Fn(_Args...), true, false>
{
public:
typedef decltype(declval<_Fn>()(declval<_Args>()...)) type;
};
template <class _MP, class _Tp, bool _IsMemberFunctionPtr>
struct __result_of_mp;
// member function pointer
template <class _MP, class _Tp>
struct __result_of_mp<_MP, _Tp, true>
: public __identity<typename __member_pointer_traits<_MP>::_ReturnType>
{
};
// member data pointer
template <class _MP, class _Tp, bool>
struct __result_of_mdp;
template <class _Rp, class _Class, class _Tp>
struct __result_of_mdp<_Rp _Class::*, _Tp, false>
{
typedef typename __apply_cv<decltype(*_VSTD::declval<_Tp>()), _Rp>::type& type;
};
template <class _Rp, class _Class, class _Tp>
struct __result_of_mdp<_Rp _Class::*, _Tp, true>
{
typedef typename __apply_cv<_Tp, _Rp>::type& type;
};
template <class _Rp, class _Class, class _Tp>
struct __result_of_mp<_Rp _Class::*, _Tp, false>
: public __result_of_mdp<_Rp _Class::*, _Tp,
is_base_of<_Class, typename remove_reference<_Tp>::type>::value>
{
};
template <class _Fn, class _Tp>
class __result_of<_Fn(_Tp), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class _Tp, class ..._Args>
class __result_of<_Fn(_Tp, _Args...), false, true> // _Fn must be member pointer
: public __result_of_mp<typename remove_reference<_Fn>::type,
_Tp,
is_member_function_pointer<typename remove_reference<_Fn>::type>::value>
{
};
template <class _Fn, class ..._Args>
class _LIBCPP_TEMPLATE_VIS result_of<_Fn(_Args...)>
: public __result_of<_Fn(_Args...),
is_class<typename remove_reference<_Fn>::type>::value ||
is_function<typename remove_pointer<typename remove_reference<_Fn>::type>::type>::value,
is_member_pointer<typename remove_reference<_Fn>::type>::value
>
{
};
#endif // C++03
#if _LIBCPP_STD_VER > 11
template <class _Tp> using result_of_t = typename result_of<_Tp>::type;
#endif
@ -4045,8 +3976,6 @@ _LIBCPP_INLINE_VAR constexpr bool is_nothrow_invocable_r_v
#endif // _LIBCPP_STD_VER > 14
#endif // !defined(_LIBCPP_CXX03_LANG)
template <class _Tp> struct __is_swappable;
template <class _Tp> struct __is_nothrow_swappable;

View File

@ -1,84 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// type_traits
// member_function_pointer
#define _LIBCPP_HAS_NO_VARIADICS
#include <type_traits>
#include "test_macros.h"
template <class T>
void test_member_function_pointer_imp()
{
static_assert(!std::is_void<T>::value, "");
#if TEST_STD_VER > 11
static_assert(!std::is_null_pointer<T>::value, "");
#endif
static_assert(!std::is_integral<T>::value, "");
static_assert(!std::is_floating_point<T>::value, "");
static_assert(!std::is_array<T>::value, "");
static_assert(!std::is_pointer<T>::value, "");
static_assert(!std::is_lvalue_reference<T>::value, "");
static_assert(!std::is_rvalue_reference<T>::value, "");
static_assert(!std::is_member_object_pointer<T>::value, "");
static_assert( std::is_member_function_pointer<T>::value, "");
static_assert(!std::is_enum<T>::value, "");
static_assert(!std::is_union<T>::value, "");
static_assert(!std::is_class<T>::value, "");
static_assert(!std::is_function<T>::value, "");
}
template <class T>
void test_member_function_pointer()
{
test_member_function_pointer_imp<T>();
test_member_function_pointer_imp<const T>();
test_member_function_pointer_imp<volatile T>();
test_member_function_pointer_imp<const volatile T>();
}
class Class
{
};
struct incomplete_type;
int main(int, char**)
{
test_member_function_pointer<void (Class::*)()>();
test_member_function_pointer<void (Class::*)(int)>();
test_member_function_pointer<void (Class::*)(int, char)>();
test_member_function_pointer<void (Class::*)() const>();
test_member_function_pointer<void (Class::*)(int) const>();
test_member_function_pointer<void (Class::*)(int, char) const>();
test_member_function_pointer<void (Class::*)() volatile>();
test_member_function_pointer<void (Class::*)(int) volatile>();
test_member_function_pointer<void (Class::*)(int, char) volatile>();
test_member_function_pointer<void (Class::*)(...)>();
test_member_function_pointer<void (Class::*)(int, ...)>();
test_member_function_pointer<void (Class::*)(int, char, ...)>();
test_member_function_pointer<void (Class::*)(...) const>();
test_member_function_pointer<void (Class::*)(int, ...) const>();
test_member_function_pointer<void (Class::*)(int, char, ...) const>();
test_member_function_pointer<void (Class::*)(...) volatile>();
test_member_function_pointer<void (Class::*)(int, ...) volatile>();
test_member_function_pointer<void (Class::*)(int, char, ...) volatile>();
// LWG#2582
static_assert(!std::is_member_function_pointer<incomplete_type>::value, "");
return 0;
}