bug90745.cc 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // -*- mode: c++; coding: utf-8 -*-
  2. /// @file bug90745.cc
  3. /// @brief Reduced regression from 8.3 to 9.1.
  4. // /opt/gcc-10.2/bin/g++ -o const -std=c++20 -Wall -Werror -ftemplate-backtrace-limit=0 const.cc
  5. // from redi @ #gcc
  6. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90745
  7. /*
  8. <lloda> I posted on ##C++ but maybe here is better [16:29]
  9. <lloda> https://wandbox.org/permlink/WNhI31fE28NQqIzP
  10. <lloda> error with 9.1 but fine in 8.3
  11. <lloda> not using tuple (#ifdef 0) makes the error go away [16:30]
  12. <lloda> I don't understand why cell<view<const int>> operator= is even
  13. instantiated :-/ [16:31]
  14. <redi> lloda: I'm pretty sure it's a consequence of
  15. https://gcc.gnu.org/r263625 for https://gcc.gnu.org/PR86963 but I'm not
  16. sure why yet [17:09]
  17. <redi> I think there's a failure outside the immediate context of a SFINAE
  18. check
  19. <lloda> redi: thanks [17:15]
  20. <redi> lloda: I also don't understand why cell<view<const int>> operator= is
  21. even instantiated
  22. <lloda> clang gives a similar error, only it hides the library steps. I'll try
  23. to digest the links. [17:27]
  24. <redi> lloda: yeah I see the problem. It's as I thought [17:34]
  25. <redi> the copy assignment operator of std::tuple now uses
  26. conditional<__assignable<const _T1&, const _T2&>(), const tuple&, const
  27. __nonesuch_no_braces&>
  28. <redi> but it's not a dependent context, so SFINAE doesn't apply
  29. <redi> the __is_assignable check blows up [17:35]
  30. <redi> the instantiation of std::tuple<x,y> triggers the instantiations of its
  31. copy assignment operator (because it's not a template) and that blows
  32. up [17:36]
  33. <redi> drat, I need to fix this
  34. <zid> Agreed, burn the C++ spec [17:37]
  35. */
  36. #include <tuple>
  37. template <class Op, class P0, class P1>
  38. struct Expr
  39. {
  40. Op op;
  41. std::tuple<P0, P1> t;
  42. using R = decltype(op(*(std::get<0>(t).p), *(std::get<1>(t).p)));
  43. operator R() { return op(*(std::get<0>(t).p), *(std::get<1>(t).p)); }
  44. };
  45. template <class Op, class P0, class P1> inline auto
  46. expr(Op && op, P0 && p0, P1 && p1)
  47. {
  48. return Expr<Op, P0, P1> { op, { p0, p1 } };
  49. }
  50. template <class Op, class P0, class P1> inline void
  51. for_each(Op && op, P0 && p0, P1 && p1)
  52. {
  53. expr(op, p0, p1);
  54. }
  55. template <class V>
  56. struct cell
  57. {
  58. typename V::value_type * p;
  59. cell(typename V::value_type * p_): p { p_ } {}
  60. template <class X> decltype(auto) operator =(X && x)
  61. {
  62. for_each([](auto && y, auto && x)
  63. { y = x; },
  64. *this, x);
  65. }
  66. };
  67. template <class T>
  68. struct view
  69. {
  70. T * p;
  71. using value_type = T;
  72. cell<view<T>> iter() { return p; }
  73. cell<view<T const>> iter() const { return p; }
  74. view(T * p_): p(p_) {}
  75. };
  76. int main()
  77. {
  78. {
  79. int cdata[2] = {44, 44};
  80. int ndata[2] = {77, 77};
  81. view<int> const c {cdata};
  82. view<int> n {ndata};
  83. for_each([](auto && n, auto && c) { n = c; }, n.iter(), c.iter());
  84. }
  85. }