Home | History | Annotate | Download | only in experimental
      1 // -*- C++ -*-
      2 //===-------------------------- type_traits -------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 #ifndef _LIBCPP_EXPERIMENTAL_TYPE_TRAITS
     12 #define _LIBCPP_EXPERIMENTAL_TYPE_TRAITS
     13 
     14 /**
     15     experimental/type_traits synopsis
     16 
     17 // C++1y
     18 #include <type_traits>
     19 
     20 namespace std {
     21 namespace experimental {
     22 inline namespace fundamentals_v1 {
     23 
     24   // See C++14 20.10.4.1, primary type categories
     25   template <class T> constexpr bool is_void_v
     26     = is_void<T>::value;
     27   template <class T> constexpr bool is_null_pointer_v
     28     = is_null_pointer<T>::value;
     29   template <class T> constexpr bool is_integral_v
     30     = is_integral<T>::value;
     31   template <class T> constexpr bool is_floating_point_v
     32     = is_floating_point<T>::value;
     33   template <class T> constexpr bool is_array_v
     34     = is_array<T>::value;
     35   template <class T> constexpr bool is_pointer_v
     36     = is_pointer<T>::value;
     37   template <class T> constexpr bool is_lvalue_reference_v
     38     = is_lvalue_reference<T>::value;
     39   template <class T> constexpr bool is_rvalue_reference_v
     40     = is_rvalue_reference<T>::value;
     41   template <class T> constexpr bool is_member_object_pointer_v
     42     = is_member_object_pointer<T>::value;
     43   template <class T> constexpr bool is_member_function_pointer_v
     44     = is_member_function_pointer<T>::value;
     45   template <class T> constexpr bool is_enum_v
     46     = is_enum<T>::value;
     47   template <class T> constexpr bool is_union_v
     48     = is_union<T>::value;
     49   template <class T> constexpr bool is_class_v
     50     = is_class<T>::value;
     51   template <class T> constexpr bool is_function_v
     52     = is_function<T>::value;
     53 
     54   // See C++14 20.10.4.2, composite type categories
     55   template <class T> constexpr bool is_reference_v
     56     = is_reference<T>::value;
     57   template <class T> constexpr bool is_arithmetic_v
     58     = is_arithmetic<T>::value;
     59   template <class T> constexpr bool is_fundamental_v
     60     = is_fundamental<T>::value;
     61   template <class T> constexpr bool is_object_v
     62     = is_object<T>::value;
     63   template <class T> constexpr bool is_scalar_v
     64     = is_scalar<T>::value;
     65   template <class T> constexpr bool is_compound_v
     66     = is_compound<T>::value;
     67   template <class T> constexpr bool is_member_pointer_v
     68     = is_member_pointer<T>::value;
     69 
     70   // See C++14 20.10.4.3, type properties
     71   template <class T> constexpr bool is_const_v
     72     = is_const<T>::value;
     73   template <class T> constexpr bool is_volatile_v
     74     = is_volatile<T>::value;
     75   template <class T> constexpr bool is_trivial_v
     76     = is_trivial<T>::value;
     77   template <class T> constexpr bool is_trivially_copyable_v
     78     = is_trivially_copyable<T>::value;
     79   template <class T> constexpr bool is_standard_layout_v
     80     = is_standard_layout<T>::value;
     81   template <class T> constexpr bool is_pod_v
     82     = is_pod<T>::value;
     83   template <class T> constexpr bool is_literal_type_v
     84     = is_literal_type<T>::value;
     85   template <class T> constexpr bool is_empty_v
     86     = is_empty<T>::value;
     87   template <class T> constexpr bool is_polymorphic_v
     88     = is_polymorphic<T>::value;
     89   template <class T> constexpr bool is_abstract_v
     90     = is_abstract<T>::value;
     91   template <class T> constexpr bool is_final_v
     92     = is_final<T>::value;
     93   template <class T> constexpr bool is_signed_v
     94     = is_signed<T>::value;
     95   template <class T> constexpr bool is_unsigned_v
     96     = is_unsigned<T>::value;
     97   template <class T, class... Args> constexpr bool is_constructible_v
     98     = is_constructible<T, Args...>::value;
     99   template <class T> constexpr bool is_default_constructible_v
    100     = is_default_constructible<T>::value;
    101   template <class T> constexpr bool is_copy_constructible_v
    102     = is_copy_constructible<T>::value;
    103   template <class T> constexpr bool is_move_constructible_v
    104     = is_move_constructible<T>::value;
    105   template <class T, class U> constexpr bool is_assignable_v
    106     = is_assignable<T, U>::value;
    107   template <class T> constexpr bool is_copy_assignable_v
    108     = is_copy_assignable<T>::value;
    109   template <class T> constexpr bool is_move_assignable_v
    110     = is_move_assignable<T>::value;
    111   template <class T> constexpr bool is_destructible_v
    112     = is_destructible<T>::value;
    113   template <class T, class... Args> constexpr bool is_trivially_constructible_v
    114     = is_trivially_constructible<T, Args...>::value;
    115   template <class T> constexpr bool is_trivially_default_constructible_v
    116     = is_trivially_default_constructible<T>::value;
    117   template <class T> constexpr bool is_trivially_copy_constructible_v
    118     = is_trivially_copy_constructible<T>::value;
    119   template <class T> constexpr bool is_trivially_move_constructible_v
    120     = is_trivially_move_constructible<T>::value;
    121   template <class T, class U> constexpr bool is_trivially_assignable_v
    122     = is_trivially_assignable<T, U>::value;
    123   template <class T> constexpr bool is_trivially_copy_assignable_v
    124     = is_trivially_copy_assignable<T>::value;
    125   template <class T> constexpr bool is_trivially_move_assignable_v
    126     = is_trivially_move_assignable<T>::value;
    127   template <class T> constexpr bool is_trivially_destructible_v
    128     = is_trivially_destructible<T>::value;
    129   template <class T, class... Args> constexpr bool is_nothrow_constructible_v
    130     = is_nothrow_constructible<T, Args...>::value;
    131   template <class T> constexpr bool is_nothrow_default_constructible_v
    132     = is_nothrow_default_constructible<T>::value;
    133   template <class T> constexpr bool is_nothrow_copy_constructible_v
    134     = is_nothrow_copy_constructible<T>::value;
    135   template <class T> constexpr bool is_nothrow_move_constructible_v
    136     = is_nothrow_move_constructible<T>::value;
    137   template <class T, class U> constexpr bool is_nothrow_assignable_v
    138     = is_nothrow_assignable<T, U>::value;
    139   template <class T> constexpr bool is_nothrow_copy_assignable_v
    140     = is_nothrow_copy_assignable<T>::value;
    141   template <class T> constexpr bool is_nothrow_move_assignable_v
    142     = is_nothrow_move_assignable<T>::value;
    143   template <class T> constexpr bool is_nothrow_destructible_v
    144     = is_nothrow_destructible<T>::value;
    145   template <class T> constexpr bool has_virtual_destructor_v
    146     = has_virtual_destructor<T>::value;
    147 
    148   // See C++14 20.10.5, type property queries
    149   template <class T> constexpr size_t alignment_of_v
    150     = alignment_of<T>::value;
    151   template <class T> constexpr size_t rank_v
    152     = rank<T>::value;
    153   template <class T, unsigned I = 0> constexpr size_t extent_v
    154     = extent<T, I>::value;
    155 
    156   // See C++14 20.10.6, type relations
    157   template <class T, class U> constexpr bool is_same_v
    158     = is_same<T, U>::value;
    159   template <class Base, class Derived> constexpr bool is_base_of_v
    160     = is_base_of<Base, Derived>::value;
    161   template <class From, class To> constexpr bool is_convertible_v
    162     = is_convertible<From, To>::value;
    163 
    164   // 3.3.2, Other type transformations
    165   template <class> class invocation_type; // not defined
    166   template <class F, class... ArgTypes> class invocation_type<F(ArgTypes...)>;
    167   template <class> class raw_invocation_type; // not defined
    168   template <class F, class... ArgTypes> class raw_invocation_type<F(ArgTypes...)>;
    169 
    170   template <class T>
    171     using invocation_type_t = typename invocation_type<T>::type;
    172   template <class T>
    173     using raw_invocation_type_t = typename raw_invocation_type<T>::type;
    174 
    175   // 3.3.3, Logical operator traits
    176   template<class... B> struct conjunction;
    177   template<class... B> constexpr bool conjunction_v = conjunction<B...>::value;
    178   template<class... B> struct disjunction;
    179   template<class... B> constexpr bool disjunction_v = disjunction<B...>::value;
    180   template<class B> struct negation;
    181   template<class B> constexpr bool negation_v = negation<B>::value;
    182 
    183   // 3.3.4, Detection idiom
    184   template <class...> using void_t = void;
    185 
    186   struct nonesuch {
    187     nonesuch() = delete;
    188     ~nonesuch() = delete;
    189     nonesuch(nonesuch const&) = delete;
    190     void operator=(nonesuch const&) = delete;
    191   };
    192 
    193   template <template<class...> class Op, class... Args>
    194     using is_detected = see below;
    195   template <template<class...> class Op, class... Args>
    196     constexpr bool is_detected_v = is_detected<Op, Args...>::value;
    197   template <template<class...> class Op, class... Args>
    198     using detected_t = see below;
    199   template <class Default, template<class...> class Op, class... Args>
    200     using detected_or = see below;
    201   template <class Default, template<class...> class Op, class... Args>
    202     using detected_or_t = typename detected_or<Default, Op, Args...>::type;
    203   template <class Expected, template<class...> class Op, class... Args>
    204     using is_detected_exact = is_same<Expected, detected_t<Op, Args...>>;
    205   template <class Expected, template<class...> class Op, class... Args>
    206     constexpr bool is_detected_exact_v
    207       = is_detected_exact<Expected, Op, Args...>::value;
    208   template <class To, template<class...> class Op, class... Args>
    209      using is_detected_convertible = is_convertible<detected_t<Op, Args...>, To>;
    210   template <class To, template<class...> class Op, class... Args>
    211      constexpr bool is_detected_convertible_v
    212        = is_detected_convertible<To, Op, Args...>::value;  
    213 
    214 } // namespace fundamentals_v1
    215 } // namespace experimental
    216 } // namespace std
    217 
    218  */
    219 
    220 #include <experimental/__config>
    221 
    222 #if _LIBCPP_STD_VER > 11
    223 
    224 #include <type_traits>
    225 
    226 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    227 #pragma GCC system_header
    228 #endif
    229 
    230 _LIBCPP_BEGIN_NAMESPACE_LFTS
    231 
    232 #ifndef _LIBCPP_HAS_NO_VARIABLE_TEMPLATES
    233 
    234 // C++14 20.10.4.1, primary type categories
    235 
    236 template <class _Tp> _LIBCPP_CONSTEXPR bool is_void_v
    237     = is_void<_Tp>::value;
    238 
    239 template <class _Tp> _LIBCPP_CONSTEXPR bool is_null_pointer_v
    240     = is_null_pointer<_Tp>::value;
    241 
    242 template <class _Tp> _LIBCPP_CONSTEXPR bool is_integral_v
    243     = is_integral<_Tp>::value;
    244 
    245 template <class _Tp> _LIBCPP_CONSTEXPR bool is_floating_point_v
    246     = is_floating_point<_Tp>::value;
    247 
    248 template <class _Tp> _LIBCPP_CONSTEXPR bool is_array_v
    249     = is_array<_Tp>::value;
    250 
    251 template <class _Tp> _LIBCPP_CONSTEXPR bool is_pointer_v
    252     = is_pointer<_Tp>::value;
    253 
    254 template <class _Tp> _LIBCPP_CONSTEXPR bool is_lvalue_reference_v
    255     = is_lvalue_reference<_Tp>::value;
    256 
    257 template <class _Tp> _LIBCPP_CONSTEXPR bool is_rvalue_reference_v
    258     = is_rvalue_reference<_Tp>::value;
    259 
    260 template <class _Tp> _LIBCPP_CONSTEXPR bool is_member_object_pointer_v
    261     = is_member_object_pointer<_Tp>::value;
    262 
    263 template <class _Tp> _LIBCPP_CONSTEXPR bool is_member_function_pointer_v
    264     = is_member_function_pointer<_Tp>::value;
    265 
    266 template <class _Tp> _LIBCPP_CONSTEXPR bool is_enum_v
    267     = is_enum<_Tp>::value;
    268 
    269 template <class _Tp> _LIBCPP_CONSTEXPR bool is_union_v
    270     = is_union<_Tp>::value;
    271 
    272 template <class _Tp> _LIBCPP_CONSTEXPR bool is_class_v
    273     = is_class<_Tp>::value;
    274 
    275 template <class _Tp> _LIBCPP_CONSTEXPR bool is_function_v
    276     = is_function<_Tp>::value;
    277 
    278 // C++14 20.10.4.2,  composite type categories
    279 
    280 template <class _Tp> _LIBCPP_CONSTEXPR bool is_reference_v
    281     = is_reference<_Tp>::value;
    282 
    283 template <class _Tp> _LIBCPP_CONSTEXPR bool is_arithmetic_v
    284     = is_arithmetic<_Tp>::value;
    285 
    286 template <class _Tp> _LIBCPP_CONSTEXPR bool is_fundamental_v
    287     = is_fundamental<_Tp>::value;
    288 
    289 template <class _Tp> _LIBCPP_CONSTEXPR bool is_object_v
    290     = is_object<_Tp>::value;
    291 
    292 template <class _Tp> _LIBCPP_CONSTEXPR bool is_scalar_v
    293     = is_scalar<_Tp>::value;
    294 
    295 template <class _Tp> _LIBCPP_CONSTEXPR bool is_compound_v
    296     = is_compound<_Tp>::value;
    297 
    298 template <class _Tp> _LIBCPP_CONSTEXPR bool is_member_pointer_v
    299     = is_member_pointer<_Tp>::value;
    300 
    301 // C++14 20.10.4.3, type properties
    302 
    303 template <class _Tp> _LIBCPP_CONSTEXPR bool is_const_v
    304     = is_const<_Tp>::value;
    305 
    306 template <class _Tp> _LIBCPP_CONSTEXPR bool is_volatile_v
    307     = is_volatile<_Tp>::value;
    308 
    309 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivial_v
    310     = is_trivial<_Tp>::value;
    311 
    312 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivially_copyable_v
    313     = is_trivially_copyable<_Tp>::value;
    314 
    315 template <class _Tp> _LIBCPP_CONSTEXPR bool is_standard_layout_v
    316     = is_standard_layout<_Tp>::value;
    317 
    318 template <class _Tp> _LIBCPP_CONSTEXPR bool is_pod_v
    319     = is_pod<_Tp>::value;
    320 
    321 template <class _Tp> _LIBCPP_CONSTEXPR bool is_literal_type_v
    322     = is_literal_type<_Tp>::value;
    323 
    324 template <class _Tp> _LIBCPP_CONSTEXPR bool is_empty_v
    325     = is_empty<_Tp>::value;
    326 
    327 template <class _Tp> _LIBCPP_CONSTEXPR bool is_polymorphic_v
    328     = is_polymorphic<_Tp>::value;
    329 
    330 template <class _Tp> _LIBCPP_CONSTEXPR bool is_abstract_v
    331     = is_abstract<_Tp>::value;
    332 
    333 template <class _Tp> _LIBCPP_CONSTEXPR bool is_final_v
    334     = is_final<_Tp>::value;
    335 
    336 template <class _Tp> _LIBCPP_CONSTEXPR bool is_signed_v
    337     = is_signed<_Tp>::value;
    338 
    339 template <class _Tp> _LIBCPP_CONSTEXPR bool is_unsigned_v
    340     = is_unsigned<_Tp>::value;
    341 
    342 template <class _Tp, class ..._Ts> _LIBCPP_CONSTEXPR bool is_constructible_v
    343     = is_constructible<_Tp, _Ts...>::value;
    344 
    345 template <class _Tp> _LIBCPP_CONSTEXPR bool is_default_constructible_v
    346     = is_default_constructible<_Tp>::value;
    347 
    348 template <class _Tp> _LIBCPP_CONSTEXPR bool is_copy_constructible_v
    349     = is_copy_constructible<_Tp>::value;
    350 
    351 template <class _Tp> _LIBCPP_CONSTEXPR bool is_move_constructible_v
    352     = is_move_constructible<_Tp>::value;
    353 
    354 template <class _Tp, class _Up> _LIBCPP_CONSTEXPR bool is_assignable_v
    355     = is_assignable<_Tp, _Up>::value;
    356 
    357 template <class _Tp> _LIBCPP_CONSTEXPR bool is_copy_assignable_v
    358     = is_copy_assignable<_Tp>::value;
    359 
    360 template <class _Tp> _LIBCPP_CONSTEXPR bool is_move_assignable_v
    361     = is_move_assignable<_Tp>::value;
    362 
    363 template <class _Tp> _LIBCPP_CONSTEXPR bool is_destructible_v
    364     = is_destructible<_Tp>::value;
    365 
    366 template <class _Tp, class ..._Ts> _LIBCPP_CONSTEXPR bool is_trivially_constructible_v
    367     = is_trivially_constructible<_Tp, _Ts...>::value;
    368 
    369 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivially_default_constructible_v
    370     = is_trivially_default_constructible<_Tp>::value;
    371 
    372 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivially_copy_constructible_v
    373     = is_trivially_copy_constructible<_Tp>::value;
    374 
    375 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivially_move_constructible_v
    376     = is_trivially_move_constructible<_Tp>::value;
    377 
    378 template <class _Tp, class _Up> _LIBCPP_CONSTEXPR bool is_trivially_assignable_v
    379     = is_trivially_assignable<_Tp, _Up>::value;
    380 
    381 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivially_copy_assignable_v
    382     = is_trivially_copy_assignable<_Tp>::value;
    383 
    384 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivially_move_assignable_v
    385     = is_trivially_move_assignable<_Tp>::value;
    386 
    387 template <class _Tp> _LIBCPP_CONSTEXPR bool is_trivially_destructible_v
    388     = is_trivially_destructible<_Tp>::value;
    389 
    390 template <class _Tp, class ..._Ts> _LIBCPP_CONSTEXPR bool is_nothrow_constructible_v
    391     = is_nothrow_constructible<_Tp, _Ts...>::value;
    392 
    393 template <class _Tp> _LIBCPP_CONSTEXPR bool is_nothrow_default_constructible_v
    394     = is_nothrow_default_constructible<_Tp>::value;
    395 
    396 template <class _Tp> _LIBCPP_CONSTEXPR bool is_nothrow_copy_constructible_v
    397     = is_nothrow_copy_constructible<_Tp>::value;
    398 
    399 template <class _Tp> _LIBCPP_CONSTEXPR bool is_nothrow_move_constructible_v
    400     = is_nothrow_move_constructible<_Tp>::value;
    401 
    402 template <class _Tp, class _Up> _LIBCPP_CONSTEXPR bool is_nothrow_assignable_v
    403     = is_nothrow_assignable<_Tp, _Up>::value;
    404 
    405 template <class _Tp> _LIBCPP_CONSTEXPR bool is_nothrow_copy_assignable_v
    406     = is_nothrow_copy_assignable<_Tp>::value;
    407 
    408 template <class _Tp> _LIBCPP_CONSTEXPR bool is_nothrow_move_assignable_v
    409     = is_nothrow_move_assignable<_Tp>::value;
    410 
    411 template <class _Tp> _LIBCPP_CONSTEXPR bool is_nothrow_destructible_v
    412     = is_nothrow_destructible<_Tp>::value;
    413 
    414 template <class _Tp> _LIBCPP_CONSTEXPR bool has_virtual_destructor_v
    415     = has_virtual_destructor<_Tp>::value;
    416 
    417 // C++14 20.10.5, type properties queries
    418 
    419 template <class _Tp> _LIBCPP_CONSTEXPR size_t alignment_of_v
    420     = alignment_of<_Tp>::value;
    421 
    422 template <class _Tp> _LIBCPP_CONSTEXPR size_t rank_v
    423     = rank<_Tp>::value;
    424 
    425 template <class _Tp, unsigned _Id = 0> _LIBCPP_CONSTEXPR size_t extent_v
    426     = extent<_Tp, _Id>::value;
    427 
    428 // C++14 20.10.6, type relations
    429 
    430 template <class _Tp, class _Up> _LIBCPP_CONSTEXPR bool is_same_v
    431     = is_same<_Tp, _Up>::value;
    432 
    433 template <class _Tp, class _Up> _LIBCPP_CONSTEXPR bool is_base_of_v
    434     = is_base_of<_Tp, _Up>::value;
    435 
    436 template <class _Tp, class _Up> _LIBCPP_CONSTEXPR bool is_convertible_v
    437     = is_convertible<_Tp, _Up>::value;
    438 
    439 #endif /* _LIBCPP_HAS_NO_VARIABLE_TEMPLATES */
    440 
    441 // 3.3.2, Other type transformations
    442 /*
    443 template <class>
    444 class _LIBCPP_TEMPLATE_VIS raw_invocation_type;
    445 
    446 template <class _Fn, class ..._Args>
    447 class _LIBCPP_TEMPLATE_VIS raw_invocation_type<_Fn(_Args...)>;
    448 
    449 template <class>
    450 class _LIBCPP_TEMPLATE_VIS invokation_type;
    451 
    452 template <class _Fn, class ..._Args>
    453 class _LIBCPP_TEMPLATE_VIS invokation_type<_Fn(_Args...)>;
    454 
    455 template <class _Tp>
    456 using invokation_type_t = typename invokation_type<_Tp>::type;
    457 
    458 template <class _Tp>
    459 using raw_invocation_type_t = typename raw_invocation_type<_Tp>::type;
    460 */
    461 
    462 // 3.3.3, Logical operator traits
    463 template <class...> using void_t = void;
    464 
    465 template <class... _Args>
    466 struct conjunction : _VSTD::__and_<_Args...> {};
    467 template <class... _Args>
    468 _LIBCPP_CONSTEXPR bool conjunction_v = conjunction<_Args...>::value;
    469 
    470 template <class... _Args>
    471 struct disjunction : _VSTD::__or_<_Args...> {};
    472 template <class... _Args>
    473 _LIBCPP_CONSTEXPR bool disjunction_v = disjunction<_Args...>::value;
    474 
    475 template <class _Tp>
    476 struct negation : _VSTD::__not_<_Tp> {};
    477 template<class _Tp>
    478 _LIBCPP_CONSTEXPR bool negation_v = negation<_Tp>::value;
    479 
    480 // 3.3.4, Detection idiom
    481 template <class...> using void_t = void;
    482 
    483 struct nonesuch {
    484     nonesuch()  = delete;
    485     ~nonesuch() = delete;
    486     nonesuch      (nonesuch const&) = delete;
    487     void operator=(nonesuch const&) = delete;
    488   };
    489 
    490 template <class _Default, class _AlwaysVoid, template <class...> class _Op, class... _Args>
    491 struct _DETECTOR {
    492    using value_t = false_type;
    493    using type = _Default;
    494    };
    495 
    496 template <class _Default, template <class...> class _Op, class... _Args>
    497 struct _DETECTOR<_Default, void_t<_Op<_Args...>>, _Op, _Args...> {
    498    using value_t = true_type;
    499    using type = _Op<_Args...>;
    500    };
    501      
    502 
    503 template <template<class...> class _Op, class... _Args>
    504   using is_detected = typename _DETECTOR<nonesuch, void, _Op, _Args...>::value_t;
    505 template <template<class...> class _Op, class... _Args>
    506   using detected_t = typename _DETECTOR<nonesuch, void, _Op, _Args...>::type;
    507 template <template<class...> class _Op, class... _Args>
    508   _LIBCPP_CONSTEXPR bool is_detected_v = is_detected<_Op, _Args...>::value;
    509 
    510 template <class Default, template<class...> class _Op, class... _Args>
    511   using detected_or = _DETECTOR<Default, void, _Op, _Args...>;
    512 template <class Default, template<class...> class _Op, class... _Args>
    513   using detected_or_t = typename detected_or<Default, _Op, _Args...>::type;
    514 
    515 template <class Expected, template<class...> class _Op, class... _Args>
    516   using is_detected_exact = is_same<Expected, detected_t<_Op, _Args...>>;
    517 template <class Expected, template<class...> class _Op, class... _Args>
    518   _LIBCPP_CONSTEXPR bool is_detected_exact_v = is_detected_exact<Expected, _Op, _Args...>::value;
    519 
    520 template <class To, template<class...> class _Op, class... _Args>
    521   using is_detected_convertible = is_convertible<detected_t<_Op, _Args...>, To>;
    522 template <class To, template<class...> class _Op, class... _Args>
    523   _LIBCPP_CONSTEXPR bool is_detected_convertible_v = is_detected_convertible<To, _Op, _Args...>::value;  
    524 
    525 
    526 _LIBCPP_END_NAMESPACE_LFTS
    527 
    528 #endif /* _LIBCPP_STD_VER > 11 */
    529 
    530 #endif /* _LIBCPP_EXPERIMENTAL_TYPE_TRAITS */
    531