为什么这种检测习语的使用会导致 Clang 和 GCC 的不同编译错误以及 MSVC 的 none
Why does this use of the detection idiom result in different compilation errors for Clang and GCC and none for MSVC
在使用检测习惯用法和 void_t
时,我发现涉及减法运算符和 void* 的表达式会导致测试编译器出现不同的错误。
GCC 10.2 及以下版本,无论使用 C++11、14、17 还是 20,似乎都将某些表达式视为硬错误而不是替换失败。
我正在使用以下(简化的)示例
#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*");
并希望代码针对所有四种语言标准编译无误(包含 std::void_t
对 C++17 之前的替代,以便可以测试更多标准)但是
- GCC 10.2 及以下版本抱怨最后两个断言
- Clang 不抱怨
- MSVC 抱怨 int*/void* 组合
我试图搜索现有的错误报告,但找不到。
我想知道哪个编译器是正确的以及为什么。
GCC 10.2 及更早版本将 (void*)0 - (void*)0
视为硬错误而不是软错误是错误的。这在主干中是固定的。
Clang 做的一切都正确。
MSVC错误允许(int*)0 - (void*)0;
(同时正确拒绝(void*)0 - (int*)0;
),如图:
[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; ...
在使用检测习惯用法和 void_t
时,我发现涉及减法运算符和 void* 的表达式会导致测试编译器出现不同的错误。
GCC 10.2 及以下版本,无论使用 C++11、14、17 还是 20,似乎都将某些表达式视为硬错误而不是替换失败。
我正在使用以下(简化的)示例
#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*");
并希望代码针对所有四种语言标准编译无误(包含 std::void_t
对 C++17 之前的替代,以便可以测试更多标准)但是
- GCC 10.2 及以下版本抱怨最后两个断言
- Clang 不抱怨
- MSVC 抱怨 int*/void* 组合
我试图搜索现有的错误报告,但找不到。
我想知道哪个编译器是正确的以及为什么。
GCC 10.2 及更早版本将 (void*)0 - (void*)0
视为硬错误而不是软错误是错误的。这在主干中是固定的。
Clang 做的一切都正确。
MSVC错误允许(int*)0 - (void*)0;
(同时正确拒绝(void*)0 - (int*)0;
),如图:
[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; ...