1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_ANY 11#define _LIBCPP_ANY 12 13/* 14 any synopsis 15 16namespace std { 17 18 class bad_any_cast : public bad_cast 19 { 20 public: 21 virtual const char* what() const noexcept; 22 }; 23 24 class any 25 { 26 public: 27 28 // 6.3.1 any construct/destruct 29 any() noexcept; 30 31 any(const any& other); 32 any(any&& other) noexcept; 33 34 template <class ValueType> 35 any(ValueType&& value); 36 37 ~any(); 38 39 // 6.3.2 any assignments 40 any& operator=(const any& rhs); 41 any& operator=(any&& rhs) noexcept; 42 43 template <class ValueType> 44 any& operator=(ValueType&& rhs); 45 46 // 6.3.3 any modifiers 47 template <class ValueType, class... Args> 48 decay_t<ValueType>& emplace(Args&&... args); 49 template <class ValueType, class U, class... Args> 50 decay_t<ValueType>& emplace(initializer_list<U>, Args&&...); 51 void reset() noexcept; 52 void swap(any& rhs) noexcept; 53 54 // 6.3.4 any observers 55 bool has_value() const noexcept; 56 const type_info& type() const noexcept; 57 }; 58 59 // 6.4 Non-member functions 60 void swap(any& x, any& y) noexcept; 61 62 template <class T, class ...Args> 63 any make_any(Args&& ...args); 64 template <class T, class U, class ...Args> 65 any make_any(initializer_list<U>, Args&& ...args); 66 67 template<class ValueType> 68 ValueType any_cast(const any& operand); 69 template<class ValueType> 70 ValueType any_cast(any& operand); 71 template<class ValueType> 72 ValueType any_cast(any&& operand); 73 74 template<class ValueType> 75 const ValueType* any_cast(const any* operand) noexcept; 76 template<class ValueType> 77 ValueType* any_cast(any* operand) noexcept; 78 79} // namespace std 80 81*/ 82 83#include <__availability> 84#include <__config> 85#include <__utility/forward.h> 86#include <__utility/in_place.h> 87#include <__utility/move.h> 88#include <__utility/unreachable.h> 89#include <cstdlib> 90#include <memory> 91#include <type_traits> 92#include <typeinfo> 93#include <version> 94 95#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 96# pragma GCC system_header 97#endif 98 99namespace std { 100class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast 101{ 102public: 103 virtual const char* what() const _NOEXCEPT; 104}; 105} // namespace std 106 107_LIBCPP_BEGIN_NAMESPACE_STD 108 109#if _LIBCPP_STD_VER > 14 110 111_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY 112_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 113void __throw_bad_any_cast() 114{ 115#ifndef _LIBCPP_NO_EXCEPTIONS 116 throw bad_any_cast(); 117#else 118 _VSTD::abort(); 119#endif 120} 121 122// Forward declarations 123class _LIBCPP_TEMPLATE_VIS any; 124 125template <class _ValueType> 126_LIBCPP_INLINE_VISIBILITY 127add_pointer_t<add_const_t<_ValueType>> 128any_cast(any const *) _NOEXCEPT; 129 130template <class _ValueType> 131_LIBCPP_INLINE_VISIBILITY 132add_pointer_t<_ValueType> any_cast(any *) _NOEXCEPT; 133 134namespace __any_imp 135{ 136 using _Buffer = aligned_storage_t<3*sizeof(void*), alignment_of<void*>::value>; 137 138 template <class _Tp> 139 using _IsSmallObject = integral_constant<bool 140 , sizeof(_Tp) <= sizeof(_Buffer) 141 && alignment_of<_Buffer>::value 142 % alignment_of<_Tp>::value == 0 143 && is_nothrow_move_constructible<_Tp>::value 144 >; 145 146 enum class _Action { 147 _Destroy, 148 _Copy, 149 _Move, 150 _Get, 151 _TypeInfo 152 }; 153 154 template <class _Tp> struct _SmallHandler; 155 template <class _Tp> struct _LargeHandler; 156 157 template <class _Tp> 158 struct _LIBCPP_TEMPLATE_VIS __unique_typeinfo { static constexpr int __id = 0; }; 159 template <class _Tp> constexpr int __unique_typeinfo<_Tp>::__id; 160 161 template <class _Tp> 162 inline _LIBCPP_INLINE_VISIBILITY 163 constexpr const void* __get_fallback_typeid() { 164 return &__unique_typeinfo<remove_cv_t<remove_reference_t<_Tp>>>::__id; 165 } 166 167 template <class _Tp> 168 inline _LIBCPP_INLINE_VISIBILITY 169 bool __compare_typeid(type_info const* __id, const void* __fallback_id) 170 { 171#if !defined(_LIBCPP_NO_RTTI) 172 if (__id && *__id == typeid(_Tp)) 173 return true; 174#endif 175 if (!__id && __fallback_id == __any_imp::__get_fallback_typeid<_Tp>()) 176 return true; 177 return false; 178 } 179 180 template <class _Tp> 181 using _Handler = conditional_t< 182 _IsSmallObject<_Tp>::value, _SmallHandler<_Tp>, _LargeHandler<_Tp>>; 183 184} // namespace __any_imp 185 186class _LIBCPP_TEMPLATE_VIS any 187{ 188public: 189 // construct/destruct 190 _LIBCPP_INLINE_VISIBILITY 191 constexpr any() _NOEXCEPT : __h(nullptr) {} 192 193 _LIBCPP_INLINE_VISIBILITY 194 any(any const & __other) : __h(nullptr) 195 { 196 if (__other.__h) __other.__call(_Action::_Copy, this); 197 } 198 199 _LIBCPP_INLINE_VISIBILITY 200 any(any && __other) _NOEXCEPT : __h(nullptr) 201 { 202 if (__other.__h) __other.__call(_Action::_Move, this); 203 } 204 205 template < 206 class _ValueType 207 , class _Tp = decay_t<_ValueType> 208 , class = enable_if_t< 209 !is_same<_Tp, any>::value && 210 !__is_inplace_type<_ValueType>::value && 211 is_copy_constructible<_Tp>::value> 212 > 213 _LIBCPP_INLINE_VISIBILITY 214 any(_ValueType && __value); 215 216 template <class _ValueType, class ..._Args, 217 class _Tp = decay_t<_ValueType>, 218 class = enable_if_t< 219 is_constructible<_Tp, _Args...>::value && 220 is_copy_constructible<_Tp>::value 221 > 222 > 223 _LIBCPP_INLINE_VISIBILITY 224 explicit any(in_place_type_t<_ValueType>, _Args&&... __args); 225 226 template <class _ValueType, class _Up, class ..._Args, 227 class _Tp = decay_t<_ValueType>, 228 class = enable_if_t< 229 is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value && 230 is_copy_constructible<_Tp>::value> 231 > 232 _LIBCPP_INLINE_VISIBILITY 233 explicit any(in_place_type_t<_ValueType>, initializer_list<_Up>, _Args&&... __args); 234 235 _LIBCPP_INLINE_VISIBILITY 236 ~any() { this->reset(); } 237 238 // assignments 239 _LIBCPP_INLINE_VISIBILITY 240 any & operator=(any const & __rhs) { 241 any(__rhs).swap(*this); 242 return *this; 243 } 244 245 _LIBCPP_INLINE_VISIBILITY 246 any & operator=(any && __rhs) _NOEXCEPT { 247 any(_VSTD::move(__rhs)).swap(*this); 248 return *this; 249 } 250 251 template < 252 class _ValueType 253 , class _Tp = decay_t<_ValueType> 254 , class = enable_if_t< 255 !is_same<_Tp, any>::value 256 && is_copy_constructible<_Tp>::value> 257 > 258 _LIBCPP_INLINE_VISIBILITY 259 any & operator=(_ValueType && __rhs); 260 261 template <class _ValueType, class ..._Args, 262 class _Tp = decay_t<_ValueType>, 263 class = enable_if_t< 264 is_constructible<_Tp, _Args...>::value && 265 is_copy_constructible<_Tp>::value> 266 > 267 _LIBCPP_INLINE_VISIBILITY 268 _Tp& emplace(_Args&&... args); 269 270 template <class _ValueType, class _Up, class ..._Args, 271 class _Tp = decay_t<_ValueType>, 272 class = enable_if_t< 273 is_constructible<_Tp, initializer_list<_Up>&, _Args...>::value && 274 is_copy_constructible<_Tp>::value> 275 > 276 _LIBCPP_INLINE_VISIBILITY 277 _Tp& emplace(initializer_list<_Up>, _Args&&...); 278 279 // 6.3.3 any modifiers 280 _LIBCPP_INLINE_VISIBILITY 281 void reset() _NOEXCEPT { if (__h) this->__call(_Action::_Destroy); } 282 283 _LIBCPP_INLINE_VISIBILITY 284 void swap(any & __rhs) _NOEXCEPT; 285 286 // 6.3.4 any observers 287 _LIBCPP_INLINE_VISIBILITY 288 bool has_value() const _NOEXCEPT { return __h != nullptr; } 289 290#if !defined(_LIBCPP_NO_RTTI) 291 _LIBCPP_INLINE_VISIBILITY 292 const type_info & type() const _NOEXCEPT { 293 if (__h) { 294 return *static_cast<type_info const *>(this->__call(_Action::_TypeInfo)); 295 } else { 296 return typeid(void); 297 } 298 } 299#endif 300 301private: 302 typedef __any_imp::_Action _Action; 303 using _HandleFuncPtr = void* (*)(_Action, any const *, any *, const type_info *, 304 const void* __fallback_info); 305 306 union _Storage { 307 constexpr _Storage() : __ptr(nullptr) {} 308 void * __ptr; 309 __any_imp::_Buffer __buf; 310 }; 311 312 _LIBCPP_INLINE_VISIBILITY 313 void * __call(_Action __a, any * __other = nullptr, 314 type_info const * __info = nullptr, 315 const void* __fallback_info = nullptr) const 316 { 317 return __h(__a, this, __other, __info, __fallback_info); 318 } 319 320 _LIBCPP_INLINE_VISIBILITY 321 void * __call(_Action __a, any * __other = nullptr, 322 type_info const * __info = nullptr, 323 const void* __fallback_info = nullptr) 324 { 325 return __h(__a, this, __other, __info, __fallback_info); 326 } 327 328 template <class> 329 friend struct __any_imp::_SmallHandler; 330 template <class> 331 friend struct __any_imp::_LargeHandler; 332 333 template <class _ValueType> 334 friend add_pointer_t<add_const_t<_ValueType>> 335 any_cast(any const *) _NOEXCEPT; 336 337 template <class _ValueType> 338 friend add_pointer_t<_ValueType> 339 any_cast(any *) _NOEXCEPT; 340 341 _HandleFuncPtr __h = nullptr; 342 _Storage __s; 343}; 344 345namespace __any_imp 346{ 347 template <class _Tp> 348 struct _LIBCPP_TEMPLATE_VIS _SmallHandler 349 { 350 _LIBCPP_INLINE_VISIBILITY 351 static void* __handle(_Action __act, any const * __this, any * __other, 352 type_info const * __info, const void* __fallback_info) 353 { 354 switch (__act) 355 { 356 case _Action::_Destroy: 357 __destroy(const_cast<any &>(*__this)); 358 return nullptr; 359 case _Action::_Copy: 360 __copy(*__this, *__other); 361 return nullptr; 362 case _Action::_Move: 363 __move(const_cast<any &>(*__this), *__other); 364 return nullptr; 365 case _Action::_Get: 366 return __get(const_cast<any &>(*__this), __info, __fallback_info); 367 case _Action::_TypeInfo: 368 return __type_info(); 369 } 370 __libcpp_unreachable(); 371 } 372 373 template <class ..._Args> 374 _LIBCPP_INLINE_VISIBILITY 375 static _Tp& __create(any & __dest, _Args&&... __args) { 376 typedef allocator<_Tp> _Alloc; 377 typedef allocator_traits<_Alloc> _ATraits; 378 _Alloc __a; 379 _Tp * __ret = static_cast<_Tp*>(static_cast<void*>(&__dest.__s.__buf)); 380 _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...); 381 __dest.__h = &_SmallHandler::__handle; 382 return *__ret; 383 } 384 385 private: 386 _LIBCPP_INLINE_VISIBILITY 387 static void __destroy(any & __this) { 388 typedef allocator<_Tp> _Alloc; 389 typedef allocator_traits<_Alloc> _ATraits; 390 _Alloc __a; 391 _Tp * __p = static_cast<_Tp *>(static_cast<void*>(&__this.__s.__buf)); 392 _ATraits::destroy(__a, __p); 393 __this.__h = nullptr; 394 } 395 396 _LIBCPP_INLINE_VISIBILITY 397 static void __copy(any const & __this, any & __dest) { 398 _SmallHandler::__create(__dest, *static_cast<_Tp const *>( 399 static_cast<void const *>(&__this.__s.__buf))); 400 } 401 402 _LIBCPP_INLINE_VISIBILITY 403 static void __move(any & __this, any & __dest) { 404 _SmallHandler::__create(__dest, _VSTD::move( 405 *static_cast<_Tp*>(static_cast<void*>(&__this.__s.__buf)))); 406 __destroy(__this); 407 } 408 409 _LIBCPP_INLINE_VISIBILITY 410 static void* __get(any & __this, 411 type_info const * __info, 412 const void* __fallback_id) 413 { 414 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_id)) 415 return static_cast<void*>(&__this.__s.__buf); 416 return nullptr; 417 } 418 419 _LIBCPP_INLINE_VISIBILITY 420 static void* __type_info() 421 { 422#if !defined(_LIBCPP_NO_RTTI) 423 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 424#else 425 return nullptr; 426#endif 427 } 428 }; 429 430 template <class _Tp> 431 struct _LIBCPP_TEMPLATE_VIS _LargeHandler 432 { 433 _LIBCPP_INLINE_VISIBILITY 434 static void* __handle(_Action __act, any const * __this, 435 any * __other, type_info const * __info, 436 void const* __fallback_info) 437 { 438 switch (__act) 439 { 440 case _Action::_Destroy: 441 __destroy(const_cast<any &>(*__this)); 442 return nullptr; 443 case _Action::_Copy: 444 __copy(*__this, *__other); 445 return nullptr; 446 case _Action::_Move: 447 __move(const_cast<any &>(*__this), *__other); 448 return nullptr; 449 case _Action::_Get: 450 return __get(const_cast<any &>(*__this), __info, __fallback_info); 451 case _Action::_TypeInfo: 452 return __type_info(); 453 } 454 __libcpp_unreachable(); 455 } 456 457 template <class ..._Args> 458 _LIBCPP_INLINE_VISIBILITY 459 static _Tp& __create(any & __dest, _Args&&... __args) { 460 typedef allocator<_Tp> _Alloc; 461 typedef allocator_traits<_Alloc> _ATraits; 462 typedef __allocator_destructor<_Alloc> _Dp; 463 _Alloc __a; 464 unique_ptr<_Tp, _Dp> __hold(_ATraits::allocate(__a, 1), _Dp(__a, 1)); 465 _Tp * __ret = __hold.get(); 466 _ATraits::construct(__a, __ret, _VSTD::forward<_Args>(__args)...); 467 __dest.__s.__ptr = __hold.release(); 468 __dest.__h = &_LargeHandler::__handle; 469 return *__ret; 470 } 471 472 private: 473 474 _LIBCPP_INLINE_VISIBILITY 475 static void __destroy(any & __this){ 476 typedef allocator<_Tp> _Alloc; 477 typedef allocator_traits<_Alloc> _ATraits; 478 _Alloc __a; 479 _Tp * __p = static_cast<_Tp *>(__this.__s.__ptr); 480 _ATraits::destroy(__a, __p); 481 _ATraits::deallocate(__a, __p, 1); 482 __this.__h = nullptr; 483 } 484 485 _LIBCPP_INLINE_VISIBILITY 486 static void __copy(any const & __this, any & __dest) { 487 _LargeHandler::__create(__dest, *static_cast<_Tp const *>(__this.__s.__ptr)); 488 } 489 490 _LIBCPP_INLINE_VISIBILITY 491 static void __move(any & __this, any & __dest) { 492 __dest.__s.__ptr = __this.__s.__ptr; 493 __dest.__h = &_LargeHandler::__handle; 494 __this.__h = nullptr; 495 } 496 497 _LIBCPP_INLINE_VISIBILITY 498 static void* __get(any & __this, type_info const * __info, 499 void const* __fallback_info) 500 { 501 if (__any_imp::__compare_typeid<_Tp>(__info, __fallback_info)) 502 return static_cast<void*>(__this.__s.__ptr); 503 return nullptr; 504 505 } 506 507 _LIBCPP_INLINE_VISIBILITY 508 static void* __type_info() 509 { 510#if !defined(_LIBCPP_NO_RTTI) 511 return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); 512#else 513 return nullptr; 514#endif 515 } 516 }; 517 518} // namespace __any_imp 519 520 521template <class _ValueType, class _Tp, class> 522any::any(_ValueType && __v) : __h(nullptr) 523{ 524 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_ValueType>(__v)); 525} 526 527template <class _ValueType, class ..._Args, class _Tp, class> 528any::any(in_place_type_t<_ValueType>, _Args&&... __args) { 529 __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 530} 531 532template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 533any::any(in_place_type_t<_ValueType>, initializer_list<_Up> __il, _Args&&... __args) { 534 __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); 535} 536 537template <class _ValueType, class, class> 538inline _LIBCPP_INLINE_VISIBILITY 539any & any::operator=(_ValueType && __v) 540{ 541 any(_VSTD::forward<_ValueType>(__v)).swap(*this); 542 return *this; 543} 544 545template <class _ValueType, class ..._Args, class _Tp, class> 546inline _LIBCPP_INLINE_VISIBILITY 547_Tp& any::emplace(_Args&&... __args) { 548 reset(); 549 return __any_imp::_Handler<_Tp>::__create(*this, _VSTD::forward<_Args>(__args)...); 550} 551 552template <class _ValueType, class _Up, class ..._Args, class _Tp, class> 553inline _LIBCPP_INLINE_VISIBILITY 554_Tp& any::emplace(initializer_list<_Up> __il, _Args&&... __args) { 555 reset(); 556 return __any_imp::_Handler<_Tp>::__create(*this, __il, _VSTD::forward<_Args>(__args)...); 557} 558 559inline _LIBCPP_INLINE_VISIBILITY 560void any::swap(any & __rhs) _NOEXCEPT 561{ 562 if (this == &__rhs) 563 return; 564 if (__h && __rhs.__h) { 565 any __tmp; 566 __rhs.__call(_Action::_Move, &__tmp); 567 this->__call(_Action::_Move, &__rhs); 568 __tmp.__call(_Action::_Move, this); 569 } 570 else if (__h) { 571 this->__call(_Action::_Move, &__rhs); 572 } 573 else if (__rhs.__h) { 574 __rhs.__call(_Action::_Move, this); 575 } 576} 577 578// 6.4 Non-member functions 579 580inline _LIBCPP_INLINE_VISIBILITY 581void swap(any & __lhs, any & __rhs) _NOEXCEPT 582{ 583 __lhs.swap(__rhs); 584} 585 586template <class _Tp, class ..._Args> 587inline _LIBCPP_INLINE_VISIBILITY 588any make_any(_Args&&... __args) { 589 return any(in_place_type<_Tp>, _VSTD::forward<_Args>(__args)...); 590} 591 592template <class _Tp, class _Up, class ..._Args> 593inline _LIBCPP_INLINE_VISIBILITY 594any make_any(initializer_list<_Up> __il, _Args&&... __args) { 595 return any(in_place_type<_Tp>, __il, _VSTD::forward<_Args>(__args)...); 596} 597 598template <class _ValueType> 599inline _LIBCPP_INLINE_VISIBILITY 600_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 601_ValueType any_cast(any const & __v) 602{ 603 using _RawValueType = __uncvref_t<_ValueType>; 604 static_assert(is_constructible<_ValueType, _RawValueType const &>::value, 605 "ValueType is required to be a const lvalue reference " 606 "or a CopyConstructible type"); 607 auto __tmp = _VSTD::any_cast<add_const_t<_RawValueType>>(&__v); 608 if (__tmp == nullptr) 609 __throw_bad_any_cast(); 610 return static_cast<_ValueType>(*__tmp); 611} 612 613template <class _ValueType> 614inline _LIBCPP_INLINE_VISIBILITY 615_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 616_ValueType any_cast(any & __v) 617{ 618 using _RawValueType = __uncvref_t<_ValueType>; 619 static_assert(is_constructible<_ValueType, _RawValueType &>::value, 620 "ValueType is required to be an lvalue reference " 621 "or a CopyConstructible type"); 622 auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); 623 if (__tmp == nullptr) 624 __throw_bad_any_cast(); 625 return static_cast<_ValueType>(*__tmp); 626} 627 628template <class _ValueType> 629inline _LIBCPP_INLINE_VISIBILITY 630_LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST 631_ValueType any_cast(any && __v) 632{ 633 using _RawValueType = __uncvref_t<_ValueType>; 634 static_assert(is_constructible<_ValueType, _RawValueType>::value, 635 "ValueType is required to be an rvalue reference " 636 "or a CopyConstructible type"); 637 auto __tmp = _VSTD::any_cast<_RawValueType>(&__v); 638 if (__tmp == nullptr) 639 __throw_bad_any_cast(); 640 return static_cast<_ValueType>(_VSTD::move(*__tmp)); 641} 642 643template <class _ValueType> 644inline _LIBCPP_INLINE_VISIBILITY 645add_pointer_t<add_const_t<_ValueType>> 646any_cast(any const * __any) _NOEXCEPT 647{ 648 static_assert(!is_reference<_ValueType>::value, 649 "_ValueType may not be a reference."); 650 return _VSTD::any_cast<_ValueType>(const_cast<any *>(__any)); 651} 652 653template <class _RetType> 654inline _LIBCPP_INLINE_VISIBILITY 655_RetType __pointer_or_func_cast(void* __p, /*IsFunction*/false_type) noexcept { 656 return static_cast<_RetType>(__p); 657} 658 659template <class _RetType> 660inline _LIBCPP_INLINE_VISIBILITY 661_RetType __pointer_or_func_cast(void*, /*IsFunction*/true_type) noexcept { 662 return nullptr; 663} 664 665template <class _ValueType> 666add_pointer_t<_ValueType> 667any_cast(any * __any) _NOEXCEPT 668{ 669 using __any_imp::_Action; 670 static_assert(!is_reference<_ValueType>::value, 671 "_ValueType may not be a reference."); 672 typedef typename add_pointer<_ValueType>::type _ReturnType; 673 if (__any && __any->__h) { 674 void *__p = __any->__call(_Action::_Get, nullptr, 675#if !defined(_LIBCPP_NO_RTTI) 676 &typeid(_ValueType), 677#else 678 nullptr, 679#endif 680 __any_imp::__get_fallback_typeid<_ValueType>()); 681 return _VSTD::__pointer_or_func_cast<_ReturnType>( 682 __p, is_function<_ValueType>{}); 683 } 684 return nullptr; 685} 686 687#endif // _LIBCPP_STD_VER > 14 688 689_LIBCPP_END_NAMESPACE_STD 690 691#endif // _LIBCPP_ANY 692