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

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Clang gives a different error, but no more helpful:

v.C:2:34: error: expected '(' for function-style cast or type construction
static_assert( std::is_void<void>, "void is void is void" );
               ~~~~~~~~~~~~~~~~~~^
v.C:3:38: error: expected '(' for function-style cast or type construction
constexpr bool b = std::is_void<void>;
                   ~~~~~~~~~~~~~~~~~~^
2 errors generated.

This is pointing out that std::is_void<void>() would fix it, which is true. And
it's maybe more helpful than just saying "expected primary-expression" (which
means nothing to most users). But for the specific case of type traits we can
do better: using ::value to access the static member is more efficient to
compile than constructing a temporary and then finding its implicit conversion
to bool. So we should suggest ::value and not suggest ()

Maybe for C++17 we could also recognise when the derived trait type is in
namespace std and suggest the std::is_void_v variable template instead, on the
assumption that every std:: trait has a corresponding variable template now.

Ville suggests that instead of checking for a std::integral_constant base we
could just check if there's a nested ::value that is convertible to bool. That
would make it also work for boost-style traits that use an enumerator instead
of a static member, e.g.

struct is_foo { enum value = true; }; };


So maybe if we're using C++17, and it's a type defined in namespace std that
has a base class of std::integral_constant<bool, B>, then suggest is_foo_v<T>.

Otherwise, if is_foo<T>::value exists and is convertible to bool, then suggest
is_foo<T>::value.

Otherwise, either print the current diagnostic, or maybe something more
user-friendly that says "you used a type where a value is needed", like EDG
does:

"v.C", line 2: error: type name is not allowed
  static_assert( std::is_void<void>, "void is void is void" );
                 ^

"v.C", line 3: error: type name is not allowed
  constexpr bool b = std::is_void<void>;
                     ^

Reply via email to