PR31384.pass.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. // UNSUPPORTED: c++98, c++03
  10. // <tuple>
  11. // template <class TupleLike> tuple(TupleLike&&); // libc++ extension
  12. // See llvm.org/PR31384
  13. #include <tuple>
  14. #include <cassert>
  15. #include "test_macros.h"
  16. int count = 0;
  17. struct Explicit {
  18. Explicit() = default;
  19. explicit Explicit(int) {}
  20. };
  21. struct Implicit {
  22. Implicit() = default;
  23. Implicit(int) {}
  24. };
  25. template<class T>
  26. struct Derived : std::tuple<T> {
  27. using std::tuple<T>::tuple;
  28. template<class U>
  29. operator std::tuple<U>() && { ++count; return {}; }
  30. };
  31. template<class T>
  32. struct ExplicitDerived : std::tuple<T> {
  33. using std::tuple<T>::tuple;
  34. template<class U>
  35. explicit operator std::tuple<U>() && { ++count; return {}; }
  36. };
  37. int main(int, char**) {
  38. {
  39. std::tuple<Explicit> foo = Derived<int>{42}; ((void)foo);
  40. assert(count == 1);
  41. std::tuple<Explicit> bar(Derived<int>{42}); ((void)bar);
  42. assert(count == 2);
  43. }
  44. count = 0;
  45. {
  46. std::tuple<Implicit> foo = Derived<int>{42}; ((void)foo);
  47. assert(count == 1);
  48. std::tuple<Implicit> bar(Derived<int>{42}); ((void)bar);
  49. assert(count == 2);
  50. }
  51. count = 0;
  52. {
  53. static_assert(!std::is_convertible<
  54. ExplicitDerived<int>, std::tuple<Explicit>>::value, "");
  55. std::tuple<Explicit> bar(ExplicitDerived<int>{42}); ((void)bar);
  56. assert(count == 1);
  57. }
  58. count = 0;
  59. {
  60. // FIXME: Libc++ incorrectly rejects this code.
  61. #ifndef _LIBCPP_VERSION
  62. std::tuple<Implicit> foo = ExplicitDerived<int>{42}; ((void)foo);
  63. static_assert(std::is_convertible<
  64. ExplicitDerived<int>, std::tuple<Implicit>>::value,
  65. "correct STLs accept this");
  66. #else
  67. static_assert(!std::is_convertible<
  68. ExplicitDerived<int>, std::tuple<Implicit>>::value,
  69. "libc++ incorrectly rejects this");
  70. #endif
  71. assert(count == 0);
  72. std::tuple<Implicit> bar(ExplicitDerived<int>{42}); ((void)bar);
  73. assert(count == 1);
  74. }
  75. count = 0;
  76. return 0;
  77. }