jesses
jesses

Reputation: 631

Why does this use of the detection idiom result in different compilation errors for Clang and GCC and none for MSVC

While playing around with the detection idiom and void_t I found that expressions where the subtraction operator and void* are involved lead to different errors in the tested compilers.

GCC 10.2 and below, no matter if C++11,14,17 or 20 is used, seem to treat some expressions as hard error rather then substitution failures.

I'm working with the following (striped down) example

#include <type_traits>

template< class, class, class = void >
struct has_minus_void_t : std::false_type {};
template<class T, class U>
struct has_minus_void_t<T, U, std::void_t<
    decltype(T() - U())
    >> : std::true_type {};

static_assert(has_minus_void_t<int*,int*>::value, "int*");
static_assert(!has_minus_void_t<int*,void*>::value, "intvoid*");
static_assert(!has_minus_void_t<void*,int*>::value, "voidint*");
static_assert(!has_minus_void_t<void*,void*>::value, "void*");

and would expect the code to compile without errors for all four language standards (contains a std::void_t replacement for pre C++17 so more standards can be tested) but

I tried to search for an existing bug report but couldn't find one.

I'm wondering which compiler is right and why.

Here's a godbolt.

Upvotes: 2

Views: 165

Answers (1)

HolyBlackCat
HolyBlackCat

Reputation: 96709

GCC 10.2 and earlier are wrong to treat (void*)0 - (void*)0 as a hard instead of soft error. This is fixed in trunk.

Clang does everything correctly.

MSVC is wrong to allow (int*)0 - (void*)0; (while correctly rejecting (void*)0 - (int*)0;), as shown by:

[expr.add]/2.2

For subtraction, one of the following shall hold: ...

— both operands are pointers to cv-qualified or cv-unqualified versions of the same completely-defined object type; ...

Upvotes: 5

Related Questions