mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-12 04:43:48 +00:00
Cleanup SFINAE in tuple, and add tests for reference assignment
llvm-svn: 274414
This commit is contained in:
parent
7b60958aea
commit
27cdf401ea
@ -335,11 +335,11 @@ struct __make_tuple_types_flat<_Tuple<_Types...>, __tuple_indices<_Idx...>> {
|
||||
|
||||
template <class _Vt, size_t _Np, size_t ..._Idx>
|
||||
struct __make_tuple_types_flat<array<_Vt, _Np>, __tuple_indices<_Idx...>> {
|
||||
using _Array = array<_Vt, _Np>;
|
||||
|
||||
template <size_t>
|
||||
using __value_type = _Vt;
|
||||
template <class _Tp, class _ApplyFn = __apply_cv_t<_Tp>>
|
||||
using __apply_quals = __tuple_types<
|
||||
typename _ApplyFn::template __apply<typename tuple_element<_Idx, _Array>::type>...
|
||||
typename _ApplyFn::template __apply<__value_type<_Idx>>...
|
||||
>;
|
||||
};
|
||||
|
||||
@ -371,32 +371,19 @@ template <bool ..._Pred>
|
||||
using __all = is_same<__all_dummy<_Pred...>, __all_dummy<(_Pred, true)...>>;
|
||||
|
||||
struct __tuple_sfinae_base {
|
||||
template <class ..._FromArgs, class ..._ToArgs>
|
||||
static auto __test_constructible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>)
|
||||
-> __all<typename enable_if<
|
||||
is_constructible<_ToArgs, _FromArgs>::value
|
||||
, bool>::type{true}...>;
|
||||
static auto __test_constructible(...) -> false_type;
|
||||
template <class _Types1, class _Types2>
|
||||
using __constructible = decltype(__test_constructible(_Types1{}, _Types2{}));
|
||||
template <template <class, class...> class _Trait,
|
||||
class ..._LArgs, class ..._RArgs>
|
||||
static auto __do_test(__tuple_types<_LArgs...>, __tuple_types<_RArgs...>)
|
||||
-> __all<typename enable_if<_Trait<_LArgs, _RArgs>::value, bool>::type{true}...>;
|
||||
template <template <class...> class>
|
||||
static auto __do_test(...) -> false_type;
|
||||
|
||||
template <class ..._FromArgs, class ..._ToArgs>
|
||||
static auto __test_convertible(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>)
|
||||
-> __all<typename enable_if<
|
||||
is_convertible<_FromArgs, _ToArgs>::value
|
||||
, bool>::type{true}...>;
|
||||
static auto __test_convertible(...) -> false_type;
|
||||
template <class _Types1, class _Types2>
|
||||
using __convertible = decltype(__test_convertible(_Types1{}, _Types2{}));
|
||||
|
||||
template <class ..._FromArgs, class ..._ToArgs>
|
||||
static auto __test_assignable(__tuple_types<_FromArgs...>, __tuple_types<_ToArgs...>)
|
||||
-> __all<typename enable_if<
|
||||
is_assignable<_ToArgs&, _FromArgs>::value
|
||||
, bool>::type{true}...>;
|
||||
static auto __test_assignable(...) -> false_type;
|
||||
template <class _Types1, class _Types2>
|
||||
using __assignable = decltype(__test_assignable(_Types1{}, _Types2{}));
|
||||
template <class _FromArgs, class _ToArgs>
|
||||
using __constructible = decltype(__do_test<is_constructible>(_ToArgs{}, _FromArgs{}));
|
||||
template <class _FromArgs, class _ToArgs>
|
||||
using __convertible = decltype(__do_test<is_convertible>(_FromArgs{}, _ToArgs{}));
|
||||
template <class _FromArgs, class _ToArgs>
|
||||
using __assignable = decltype(__do_test<is_assignable>(_ToArgs{}, _FromArgs{}));
|
||||
};
|
||||
|
||||
// __tuple_convertible
|
||||
@ -440,7 +427,7 @@ template <class _Tp, class _Up>
|
||||
struct __tuple_assignable<_Tp, _Up, true, true>
|
||||
: public __tuple_sfinae_base::__assignable<
|
||||
typename __make_tuple_types<_Tp>::type
|
||||
, typename __make_tuple_types<_Up>::type
|
||||
, typename __make_tuple_types<_Up&>::type
|
||||
>
|
||||
{};
|
||||
|
||||
|
@ -74,4 +74,16 @@ int main()
|
||||
assert(std::get<1>(t1) == int('a'));
|
||||
assert(std::get<2>(t1).id_ == 2);
|
||||
}
|
||||
{
|
||||
// Test that tuple evaluates correctly applies an lvalue reference
|
||||
// before evaluating is_assignable (ie 'is_assignable<int&, int&>')
|
||||
// instead of evaluating 'is_assignable<int&&, int&>' which is false.
|
||||
int x = 42;
|
||||
int y = 43;
|
||||
std::tuple<int&&> t(std::move(x));
|
||||
std::tuple<int&> t2(y);
|
||||
t = t2;
|
||||
assert(std::get<0>(t) == 43);
|
||||
assert(&std::get<0>(t) == &x);
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,13 @@ struct D
|
||||
explicit D(int i) : B(i) {}
|
||||
};
|
||||
|
||||
struct E {
|
||||
E() = default;
|
||||
E& operator=(int val) {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@ -88,4 +95,16 @@ int main()
|
||||
assert(std::get<1>(t1) == int('a'));
|
||||
assert(std::get<2>(t1)->id_ == 3);
|
||||
}
|
||||
{
|
||||
// Test that tuple evaluates correctly applies an lvalue reference
|
||||
// before evaluating is_assignable (ie 'is_assignable<int&, int&&>')
|
||||
// instead of evaluating 'is_assignable<int&&, int&&>' which is false.
|
||||
int x = 42;
|
||||
int y = 43;
|
||||
std::tuple<int&&, E> t(std::move(x), E{});
|
||||
std::tuple<int&&, int> t2(std::move(y), 44);
|
||||
t = std::move(t2);
|
||||
assert(std::get<0>(t) == 43);
|
||||
assert(&std::get<0>(t) == &x);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user