【发布时间】:2020-02-23 02:27:52
【问题描述】:
我有一个简单的代码 sn-p 我正在尝试测试数据成员:
#include <type_traits>
template< typename T0 >
using is_data_member = std::bool_constant< std::is_same_v< std::void_t< T0 >, void > >;
template< typename U,
std::add_pointer_t< std::enable_if_t<
is_data_member< decltype( std::declval< U >().a ) >::value
> > = nullptr >
auto test() {}
struct A { int a; };
struct B {};
int main() {
static_assert( is_data_member< decltype( std::declval< A >().a ) >::value );
// #1: static_assert below fails in both gcc and clang.
// static_assert( is_data_member< decltype( std::declval< B >().a ) >::value );
test< A >();
// #2: test< B >() below fails in gcc, but does not fail in clang?
test< B >();
}
使用gcc,一切正常:#1 和#2 都出现编译错误。
但是对于clang,只有#1 无法编译,而#2 可以编译。
请亲自查看:code on godbolt。
所以问题是,基本上,发生了什么?我倾向于认为clang 比gcc 更符合标准,但在这种情况下,我认为clang 是错误的?
谢谢!
【问题讨论】:
-
可能是一个(已修复的)Clang 错误。它的行为与 Clang 中继的预期一样:godbolt.org/z/Gmb9oy
-
@walnut 非常感谢。哇,没想到 2020 年会出现这么一个(微不足道的?)clang bug……你想把你的评论作为答案,让我接受吗?
-
这不是微不足道的。别名模板参数中的替换行为在 2014 年底更改为 CWG issue 1558。当在 clang 中实现该缺陷报告时,必须忽略此特定案例的更改。如果您使用更常见的
typename = std::enable_if_t<...>语法,它就可以正常工作。 -
顺便说一句。
is_data_member不像您期望的那样工作。decltype( std::declval<B>().a )在使用它的上下文中已经是替换失败。所以is_data_member在没有失败时总是std::true_type。你也可以直接使用void_t。 -
是的,
is_data_member永远不是std::false_type。我仍在试图弄清楚如何使它工作。它确实符合他的目的,但我想拥有is_data_member::value == false,然后通过enable_if失败...
标签: c++ gcc clang c++17 sfinae