https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87603

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I suspect this is the reason that our is_nothrow_convertible trait fails in
some cases:

template<typename T> T&& declval();
template<bool B> struct bool_constant { static constexpr bool value = B; };
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;

template<typename T>
struct char_traits
{
  static int length(T* p) { int n = 0; while (*p++ != T()) ++n; return n; }
};

template<typename T, typename U = char_traits<T>>
struct basic_string_view
{
  constexpr basic_string_view(T* p) noexcept : len(U::length(p)) { }
  int len;
};

template<typename From, typename To>
  class is_nothrow_convertible_helper
  {
    template<typename To1>
      static void test_aux(To1) noexcept;

    template<typename From1, typename To1,
             bool NoEx = noexcept(test_aux<To1>(declval<From1>()))>
      static bool_constant<NoEx>
      test_nothrow(int);

    template<typename, typename>
      static false_type
      test_nothrow(...);

  public:
    typedef decltype(test_nothrow<From, To>(0)) type;
  };

template<typename From, typename To>
  struct is_nothrow_convertible
  : is_nothrow_convertible_helper<From, To>::type
  { };

struct X { };

bool b = is_nothrow_convertible<X*, basic_string_view<X>>::value;


ntconv.cc: In instantiation of 'static int char_traits<T>::length(T*) [with T =
X]':
ntconv.cc:15:61:   required from 'constexpr basic_string_view<T,
U>::basic_string_view(T*) [with T = X; U = char_traits<X>]'
ntconv.cc:26:66:   required by substitution of 'template<class From1, class
To1, bool NoEx> static bool_constant<NoEx> is_nothrow_convertible_helper<X*,
basic_string_view<X> >::test_nothrow<From1, To1, NoEx>(int) [with From1 = X*;
To1 = basic_string_view<X>; bool NoEx = false]'
ntconv.cc:35:44:   required from 'class is_nothrow_convertible_helper<X*,
basic_string_view<X> >'
ntconv.cc:39:10:   required from 'struct is_nothrow_convertible<X*,
basic_string_view<X> >'
ntconv.cc:45:58:   required from here
ntconv.cc:9:52: error: no match for 'operator!=' (operand types are 'X' and
'X')
    9 |   static int length(T* p) { int n = 0; while (*p++ != T()) ++n; return
n; }
      |                                               ~~~~~^~~~~~

The basic_string_view<X>::basic_string_view(X*) ctor is ill-formed, but I don't
think it should actually need to be instantiated here in order to tell whether
it can throw. I suspect it gets instantiated because of this bug, by the
compiler trying to determine if it can throw.

I don't have a rejects-valid testcase though, so it might not matter.

Reply via email to