| //===----------------------------------------------------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H |
| #define TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H |
| |
| #include <cstddef> |
| #include <functional> |
| #include <initializer_list> |
| #include <iterator> |
| #include <memory> |
| #include <type_traits> |
| #include <utility> |
| #include <vector> |
| |
| #include "test_macros.h" |
| #if TEST_STD_VER >= 23 |
| #include "almost_satisfies_types.h" |
| #endif |
| |
| #if TEST_STD_VER >= 23 |
| |
| template <class T> |
| struct RangeT { |
| T* begin(); |
| T* end(); |
| }; |
| static_assert(std::ranges::input_range<RangeT<int>>); |
| |
| template <class T> |
| using BadRangeT = InputRangeNotDerivedFromGeneric<T>; |
| static_assert(std::ranges::range<BadRangeT<int>>); |
| static_assert(!std::ranges::input_range<BadRangeT<int>>); |
| |
| #endif |
| |
| // `SFINAEs_away` template variable checks whether the template arguments for |
| // a given template class `Instantiated` can be deduced from the given |
| // constructor parameter types `CtrArgs` using CTAD. |
| |
| template<template<typename ...> class Instantiated, class ...CtrArgs, |
| class = decltype(Instantiated(std::declval<CtrArgs>()...))> |
| std::false_type SFINAEs_away_impl(int); |
| |
| template<template<typename ...> class Instantiated, class ...CtrArgs> |
| std::true_type SFINAEs_away_impl(...); |
| |
| template<template<typename ...> class Instantiated, class ...CtrArgs> |
| constexpr bool SFINAEs_away = |
| decltype(SFINAEs_away_impl<Instantiated, CtrArgs...>(0))::value; |
| |
| struct Empty {}; |
| |
| // For sequence containers the deduction guides should be SFINAE'd away when |
| // given: |
| // - "bad" input iterators (that is, a type not qualifying as an input |
| // iterator); |
| // - a bad allocator; |
| // - a range not satisfying the `input_range` concept. |
| template<template<typename ...> class Container, typename InstantiatedContainer, typename BadAlloc = Empty> |
| constexpr void SequenceContainerDeductionGuidesSfinaeAway() { |
| using T = typename InstantiatedContainer::value_type; |
| using Alloc = std::allocator<T>; |
| using Iter = T*; |
| |
| // Note: the only requirement in the Standard is that integral types cannot be |
| // considered input iterators; however, this doesn't work for sequence |
| // containers because they have constructors of the form `(size_type count, |
| // const value_type& value)`. These constructors would be used when passing |
| // two integral types and would deduce `value_type` to be an integral type. |
| #ifdef _LIBCPP_VERSION |
| using OutputIter = std::insert_iterator<InstantiatedContainer>; |
| #endif // _LIBCPP_VERSION |
| |
| // (iter, iter) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter) |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter>); |
| |
| // (iter, iter, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, alloc) |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Alloc>); |
| // Cannot deduce from (iter, iter, BAD_alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, BadAlloc>); |
| |
| // (alloc) |
| // |
| // Cannot deduce from (alloc) |
| static_assert(SFINAEs_away<Container, Alloc>); |
| |
| #if TEST_STD_VER >= 23 |
| using BadRange = BadRangeT<T>; |
| |
| // (from_range, range) |
| // |
| // Cannot deduce from (BAD_range) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange>); |
| |
| // (from_range, range, alloc) |
| // |
| // Cannot deduce from (range, BAD_alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, RangeT<int>, BadAlloc>); |
| #endif |
| } |
| |
| // Deduction guides should be SFINAE'd away when given: |
| // - a "bad" allocator (that is, a type not qualifying as an allocator); |
| // - an allocator instead of a container; |
| // - an allocator and a container that uses a different allocator; |
| // - a range not satisfying the `input_range` concept. |
| template<template<typename ...> class Container, typename InstantiatedContainer> |
| constexpr void ContainerAdaptorDeductionGuidesSfinaeAway() { |
| using T = typename InstantiatedContainer::value_type; |
| using Alloc [[maybe_unused]] = std::allocator<T>; |
| using Iter = T*; |
| |
| using BadIter [[maybe_unused]] = int; |
| using BadAlloc = Empty; |
| |
| // (container) -- no constraints. |
| |
| // (container, alloc) |
| // |
| // Cannot deduce from (container, BAD_alloc) |
| static_assert(SFINAEs_away<Container, std::vector<T>, BadAlloc>); |
| |
| // (iter, iter) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter) |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, BadIter, BadIter>); |
| |
| #if TEST_STD_VER >= 23 |
| using BadRange = BadRangeT<T>; |
| |
| // (iter, iter, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, alloc) |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, BadIter, BadIter, Alloc>); |
| // Cannot deduce from (iter, iter, BAD_alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, BadAlloc>); |
| |
| // (from_range, range) |
| // |
| // Cannot deduce from (BAD_range) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange>); |
| |
| // (from_range, range, alloc) |
| // |
| // Cannot deduce from (range, BAD_alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, RangeT<int>, BadAlloc>); |
| #endif |
| } |
| |
| // For associative containers the deduction guides should be SFINAE'd away when |
| // given: |
| // - "bad" input iterators (that is, a type not qualifying as an input |
| // iterator); |
| // - a bad allocator; |
| // - an allocator in place of a comparator; |
| // - a range not satisfying the `input_range` concept. |
| template<template<typename ...> class Container, typename InstantiatedContainer> |
| constexpr void AssociativeContainerDeductionGuidesSfinaeAway() { |
| using ValueType = typename InstantiatedContainer::value_type; |
| using Comp = std::less<int>; |
| using Alloc = std::allocator<ValueType>; |
| using Iter = ValueType*; |
| using InitList = std::initializer_list<ValueType>; |
| |
| struct BadAlloc {}; |
| // The only requirement in the Standard is that integral types cannot be |
| // considered input iterators, beyond that it is unspecified. |
| using BadIter = int; |
| #ifdef _LIBCPP_VERSION |
| using OutputIter = std::insert_iterator<InstantiatedContainer>; |
| #endif // _LIBCPP_VERSION |
| using AllocAsComp = Alloc; |
| |
| // (iter, iter) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter>); |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter>); |
| |
| // (iter, iter, comp) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, comp) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, Comp>); |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Comp>); |
| |
| // (iter, iter, comp, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, comp, alloc) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, Comp, Alloc>); |
| LIBCPP_STATIC_ASSERT( |
| SFINAEs_away<Container, OutputIter, OutputIter, Comp, Alloc>); |
| // Cannot deduce from (iter, iter, ALLOC_as_comp, alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, AllocAsComp, Alloc>); |
| // Cannot deduce from (iter, iter, comp, BAD_alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, Comp, BadAlloc>); |
| |
| // (iter, iter, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, alloc) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, Alloc>); |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Alloc>); |
| // Note: (iter, iter, BAD_alloc) is interpreted as (iter, iter, comp) |
| // instead and fails upon instantiation. There is no requirement to SFINAE |
| // away bad comparators. |
| |
| // (init_list, comp, alloc) |
| // |
| // Cannot deduce from (init_list, ALLOC_as_comp, alloc) |
| static_assert(SFINAEs_away<Container, InitList, AllocAsComp, Alloc>); |
| // Cannot deduce from (init_list, comp, BAD_alloc) |
| static_assert(SFINAEs_away<Container, InitList, Comp, BadAlloc>); |
| |
| // (init_list, alloc) |
| // |
| // Note: (init_list, BAD_alloc) is interpreted as (init_list, comp) instead |
| // and fails upon instantiation. There is no requirement to SFINAE away bad |
| // comparators. |
| |
| #if TEST_STD_VER >= 23 |
| using Range = RangeT<ValueType>; |
| using BadRange = BadRangeT<ValueType>; |
| |
| // (from_range, range) |
| // |
| // Can deduce from (from_range, range) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range>); |
| // Cannot deduce from (from_range, BAD_range) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange>); |
| |
| // (from_range, range, comp) |
| // |
| // Can deduce from (from_range, _range, comp) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, Comp>); |
| // Cannot deduce from (from_range, BAD_range, comp) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, Comp>); |
| |
| // (from_range, range, comp, alloc) |
| // |
| // Can deduce from (from_range, range, comp, alloc) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, Comp, Alloc>); |
| // Cannot deduce from (from_range, BAD_range, comp, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, Comp, Alloc>); |
| // Cannot deduce from (from_range, range, comp, BAD_alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, Comp, BadAlloc>); |
| |
| // (from_range, range, alloc) |
| // |
| // Can deduce from (from_range, range, alloc) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, Alloc>); |
| // Cannot deduce from (from_range, BAD_range, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, Alloc>); |
| // Note: (from_range, range, BAD_alloc) is interpreted as (from_range, range, comp) instead. |
| #endif |
| } |
| |
| // For unordered containers the deduction guides should be SFINAE'd away when |
| // given: |
| // - "bad" input iterators (that is, a type not qualifying as an input |
| // iterator); |
| // - a bad allocator; |
| // - a bad hash functor (an integral type in place of a hash); |
| // - an allocator in place of a hash functor; |
| // - an allocator in place of a predicate; |
| // - a range not satisfying the `input_range` concept. |
| template<template<typename ...> class Container, typename InstantiatedContainer> |
| constexpr void UnorderedContainerDeductionGuidesSfinaeAway() { |
| using ValueType = typename InstantiatedContainer::value_type; |
| using Pred = std::equal_to<int>; |
| using Hash = std::hash<int>; |
| using Alloc = std::allocator<ValueType>; |
| using Iter = ValueType*; |
| using InitList = std::initializer_list<ValueType>; |
| |
| using BadHash = short; |
| struct BadAlloc {}; |
| // The only requirement in the Standard is that integral types cannot be |
| // considered input iterators, beyond that it is unspecified. |
| using BadIter = int; |
| #ifdef _LIBCPP_VERSION |
| using OutputIter = std::insert_iterator<InstantiatedContainer>; |
| #endif // _LIBCPP_VERSION |
| using AllocAsHash = Alloc; |
| using AllocAsPred = Alloc; |
| |
| // (iter, iter) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter>); |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter>); |
| |
| // (iter, iter, buckets) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, buckets) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, std::size_t>); |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, std::size_t>); |
| |
| // (iter, iter, buckets, hash) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, std::size_t, Hash>); |
| LIBCPP_STATIC_ASSERT( |
| SFINAEs_away<Container, OutputIter, OutputIter, std::size_t, Hash>); |
| // Cannot deduce from (iter, iter, buckets, BAD_hash) |
| static_assert(SFINAEs_away<Container, Iter, Iter, std::size_t, BadHash>); |
| // Note: (iter, iter, buckets, ALLOC_as_hash) is allowed -- it just calls |
| // (iter, iter, buckets, alloc) |
| |
| // (iter, iter, buckets, hash, pred) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, pred) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, std::size_t, Hash, Pred>); |
| LIBCPP_STATIC_ASSERT( |
| SFINAEs_away<Container, OutputIter, OutputIter, std::size_t, Hash, Pred>); |
| // Cannot deduce from (iter, iter, buckets, BAD_hash, pred) |
| static_assert(SFINAEs_away<Container, Iter, Iter, std::size_t, BadHash, Pred>); |
| // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, pred) |
| static_assert(SFINAEs_away<Container, Iter, Iter, std::size_t, AllocAsHash, Pred>); |
| // Note: (iter, iter, buckets, hash, ALLOC_as_pred) is allowed -- it just |
| // calls (iter, iter, buckets, hash, alloc) |
| |
| // (iter, iter, buckets, hash, pred, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, pred, alloc) |
| static_assert( |
| SFINAEs_away<Container, BadIter, BadIter, std::size_t, Hash, Pred, Alloc>); |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, |
| std::size_t, Hash, Pred, Alloc>); |
| // Cannot deduce from (iter, iter, buckets, BAD_hash, pred, alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, std::size_t, BadHash, Pred, Alloc>); |
| // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, pred, alloc) |
| static_assert( |
| SFINAEs_away<Container, Iter, Iter, std::size_t, AllocAsHash, Pred, Alloc>); |
| // Cannot deduce from (iter, iter, buckets, hash, ALLOC_as_pred, alloc) |
| static_assert( |
| SFINAEs_away<Container, Iter, Iter, std::size_t, Hash, AllocAsPred, Alloc>); |
| // Cannot deduce from (iter, iter, buckets, hash, pred, BAD_alloc) |
| static_assert( |
| SFINAEs_away<Container, Iter, Iter, std::size_t, Hash, Pred, BadAlloc>); |
| |
| // (iter, iter, buckets, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, buckets, alloc) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, std::size_t, Alloc>); |
| LIBCPP_STATIC_ASSERT( |
| SFINAEs_away<Container, OutputIter, OutputIter, std::size_t, Alloc>); |
| // Note: (iter, iter, buckets, BAD_alloc) is interpreted as (iter, iter, |
| // buckets, hash), which is valid because the only requirement for the hash |
| // parameter is that it's not integral. |
| |
| // (iter, iter, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, alloc) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, Alloc>); |
| LIBCPP_STATIC_ASSERT(SFINAEs_away<Container, OutputIter, OutputIter, Alloc>); |
| // Cannot deduce from (iter, iter, BAD_alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, BadAlloc>); |
| |
| // (iter, iter, buckets, hash, alloc) |
| // |
| // Cannot deduce from (BAD_iter, BAD_iter, buckets, hash, alloc) |
| static_assert(SFINAEs_away<Container, BadIter, BadIter, std::size_t, Hash, Alloc>); |
| LIBCPP_STATIC_ASSERT( |
| SFINAEs_away<Container, OutputIter, OutputIter, std::size_t, Hash, Alloc>); |
| // Cannot deduce from (iter, iter, buckets, BAD_hash, alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, std::size_t, BadHash, Alloc>); |
| // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, alloc) |
| static_assert(SFINAEs_away<Container, Iter, Iter, std::size_t, AllocAsHash, Alloc>); |
| // Note: (iter, iter, buckets, hash, BAD_alloc) is interpreted as (iter, iter, |
| // buckets, hash, pred), which is valid because there are no requirements for |
| // the predicate. |
| |
| // (init_list, buckets, hash) |
| // |
| // Cannot deduce from (init_list, buckets, BAD_hash) |
| static_assert(SFINAEs_away<Container, InitList, std::size_t, BadHash>); |
| // Note: (init_list, buckets, ALLOC_as_hash) is interpreted as (init_list, |
| // buckets, alloc), which is valid. |
| |
| // (init_list, buckets, hash, pred) |
| // |
| // Cannot deduce from (init_list, buckets, BAD_hash, pred) |
| static_assert(SFINAEs_away<Container, InitList, std::size_t, BadHash, Pred>); |
| // Cannot deduce from (init_list, buckets, ALLOC_as_hash, pred) |
| static_assert(SFINAEs_away<Container, InitList, std::size_t, AllocAsHash, Pred>); |
| // Note: (init_list, buckets, hash, ALLOC_as_pred) is interpreted as |
| // (init_list, buckets, hash, alloc), which is valid. |
| |
| // (init_list, buckets, hash, pred, alloc) |
| // |
| // Cannot deduce from (init_list, buckets, BAD_hash, pred, alloc) |
| static_assert( |
| SFINAEs_away<Container, InitList, std::size_t, BadHash, Pred, Alloc>); |
| // Cannot deduce from (init_list, buckets, ALLOC_as_hash, pred, alloc) |
| static_assert( |
| SFINAEs_away<Container, InitList, std::size_t, AllocAsHash, Pred, Alloc>); |
| // Cannot deduce from (init_list, buckets, hash, ALLOC_as_pred, alloc) |
| static_assert( |
| SFINAEs_away<Container, InitList, std::size_t, Hash, AllocAsPred, Alloc>); |
| // Cannot deduce from (init_list, buckets, hash, pred, BAD_alloc) |
| static_assert( |
| SFINAEs_away<Container, InitList, std::size_t, Hash, Pred, BadAlloc>); |
| |
| // (init_list, buckets, alloc) |
| // |
| // Note: (init_list, buckets, BAD_alloc) is interpreted as (init_list, |
| // buckets, hash), which is valid because the only requirement for the hash |
| // parameter is that it's not integral. |
| |
| // (init_list, buckets, hash, alloc) |
| // |
| // Cannot deduce from (init_list, buckets, BAD_hash, alloc) |
| static_assert(SFINAEs_away<Container, InitList, std::size_t, BadHash, Alloc>); |
| // Cannot deduce from (init_list, buckets, ALLOC_as_hash, alloc) |
| static_assert(SFINAEs_away<Container, InitList, std::size_t, AllocAsHash, Alloc>); |
| |
| // (init_list, alloc) |
| // |
| // Cannot deduce from (init_list, BAD_alloc) |
| static_assert(SFINAEs_away<Container, InitList, BadAlloc>); |
| |
| #if TEST_STD_VER >= 23 |
| using Range = RangeT<ValueType>; |
| using BadRange = BadRangeT<ValueType>; |
| |
| // (from_range, range) |
| // |
| // Can deduce from (from_range, range) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range>); |
| // Cannot deduce from (from_range, BAD_range) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange>); |
| |
| // (from_range, range, buckets) |
| // |
| // Can deduce from (from_range, range, buckets) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, std::size_t>); |
| // Cannot deduce from (from_range, BAD_range, buckets) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, std::size_t>); |
| |
| // (from_range, range, buckets, hash) |
| // |
| // Can deduce from (from_range, range, buckets, hash) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, std::size_t, Hash>); |
| // Cannot deduce from (from_range, BAD_range, buckets, hash) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, std::size_t, Hash>); |
| // Cannot deduce from (from_range, range, buckets, BAD_hash) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, std::size_t, BadHash>); |
| |
| // (from_range, range, buckets, hash, pred) |
| // |
| // Can deduce from (from_range, range, buckets, hash, pred) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, std::size_t, Hash, Pred>); |
| // Cannot deduce from (from_range, BAD_range, buckets, hash, pred) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, std::size_t, Hash, Pred>); |
| // Cannot deduce from (from_range, range, buckets, BAD_hash, pred) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, std::size_t, BadHash, Pred>); |
| |
| // (from_range, range, buckets, hash, pred, alloc) |
| // |
| // Can deduce from (from_range, range, buckets, hash, pred, alloc) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, std::size_t, Hash, Pred, Alloc>); |
| // Cannot deduce from (from_range, BAD_range, buckets, hash, pred, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, std::size_t, Hash, Pred, Alloc>); |
| // Cannot deduce from (from_range, range, buckets, BAD_hash, pred, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, std::size_t, BadHash, Pred, Alloc>); |
| // Cannot deduce from (from_range, range, buckets, hash, pred, BAD_alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, std::size_t, Hash, Pred, BadAlloc>); |
| |
| // (from_range, range, buckets, alloc) |
| // |
| // Can deduce from (from_range, range, buckets, alloc) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, std::size_t, Alloc>); |
| // Cannot deduce from (from_range, BAD_range, buckets, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, std::size_t, Alloc>); |
| // Note: (from_range, range, buckets, BAD_alloc) is interpreted as (from_range, range, buckets, hash), which is valid |
| // because the only requirement for the hash parameter is that it's not integral. |
| |
| // (from_range, range, alloc) |
| // |
| // Can deduce from (from_range, range, alloc) |
| // TODO(LWG 2713): uncomment this test once the constructor is added. |
| // static_assert(!SFINAEs_away<Container, std::from_range_t, Range, Alloc>); |
| // Cannot deduce from (from_range, BAD_range, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, Alloc>); |
| // Cannot deduce from (from_range, range, BAD_alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, BadAlloc>); |
| |
| // (from_range, range, buckets, hash, alloc) |
| // |
| // Can deduce from (from_range, range, buckets, hash, alloc) |
| static_assert(!SFINAEs_away<Container, std::from_range_t, Range, std::size_t, Hash, Alloc>); |
| // Cannot deduce from (from_range, BAD_range, buckets, hash, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, BadRange, std::size_t, Hash, Alloc>); |
| // Cannot deduce from (from_range, range, buckets, BAD_hash, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, std::size_t, BadHash, Alloc>); |
| // Cannot deduce from (from_range, range, buckets, ALLOC_as_hash, alloc) |
| static_assert(SFINAEs_away<Container, std::from_range_t, Range, std::size_t, AllocAsHash, Alloc>); |
| // Cannot deduce from (from_range, range, buckets, hash, BAD_alloc) |
| // Note: (from_range, range, buckets, hash, BAD_alloc) is interpreted as (from_range, range, buckets, hash, pred), |
| // which is valid because the only requirement for the predicate parameter is that it does not resemble an allocator. |
| #endif |
| } |
| |
| #endif // TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H |