微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么这种检测习语的使用会导致 Clang 和 GCC 的编译错误不同,而 MSVC 不会导致编译错误 [expr.add]/2.2

如何解决为什么这种检测习语的使用会导致 Clang 和 GCC 的编译错误不同,而 MSVC 不会导致编译错误 [expr.add]/2.2

在使用检测习惯用法/var 时,我发现涉及减法运算符和 void* 的表达式会导致测试编译器中出现不同的错误

GCC 10.2 及以下版本,无论使用 C++11、14、17 还是 20,似乎都将某些表达式视为硬错误而不是替换失败。

我正在使用以下(精简的)示例

void_t

并且希望代码能够针对所有四种语言标准进行编译而不会出错(包含一个 #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*,"voidint*"); static_assert(!has_minus_void_t<void*,"void*"); 替代 C++17 之前的标准,因此可以测试更多标准)但是

  • GCC 10.2 及以下版本抱怨最后两个断言
  • Clang 不会抱怨
  • MSVC 抱怨 int*/void* 组合

我试图搜索现有的错误报告,但找不到。

我想知道哪个编译器是正确的,为什么。

Here's a godbolt

解决方法

GCC 10.2 及更早版本将 (void*)0 - (void*)0 视为硬错误而不是软错误是错误的。这在后备箱中是固定的。

Clang 做的一切都是正确的。

MSVC 错误地允许 (int*)0 - (void*)0;(同时正确拒绝 (void*)0 - (int*)0;),如下所示:

[expr.add]/2.2

对于减法,应满足以下条件之一:...

——两个操作数都是指向相同完全定义对象类型的 cv 限定或 cv 非限定版本的指针; ...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。