I can see (for example) static_assert being used in basic_stringview to constrain the instantiation of it. Not the type definition.

Thus I am wondering what was/is wrong with using C++20 require, for example?

I was told standard specifically allows for wrong types to be defined; like eg tuple<void> or basic_stringview<void ***> ...

Is the following synopsis thus not following the standard?

#include <string>
#include <type_traits>

namespace {
using namespace std;

template <class _Elem, class _Traits>
#if __cplusplus >= 202002L
// C++20 (and later) code
requires  // requires-clause (ad-hoc constraint)
    is_same_v<_Elem, typename _Traits::char_type> &&
    (!is_array_v<_Elem>)&&is_trivial_v<_Elem>&& is_standard_layout_v<_Elem>
#endif
    class basic_string_view {  // wrapper for any kind of contiguous character
                               // buffer
 public:
#if __cplusplus < 202002L
  // apparently standard was/is barring std:: types to be constrained?
  // ditto this is instantiation constraint
  // as present in MS STL today
  static_assert(is_same_v<_Elem, typename _Traits::char_type>,
                "Bad char_traits for basic_string_view; "
                "N4659 24.4.2 [string.view.template]/1 \"the type "
                "traits::char_type shall name the same type as charT.\"");

  static_assert(!is_array_v<_Elem> && is_trivial_v<_Elem> &&
                    is_standard_layout_v<_Elem>,
                "The character type of basic_string_view must be a non-array "
                "trivial standard-layout type. See N4861 "
                "[strings.general]/1.");
#endif
};

using ok_sv = basic_string_view<char, std::char_traits<char> >;

}  // namespace