数据成员 SFINAE 的 C++17 测试:gcc vs clang
C++17 testing for data-member SFINAE: gcc vs clang
我有一个简单的代码片段,我在其中尝试测试数据成员:
#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 主干,替换如预期的那样失败。
我猜这是通过 this bug report 解决的,根据别名模板(例如 is_data_member
)的参数,如果它们出现在非类型模板的类型说明符中,则在替换期间未被正确处理参数.
我有一个简单的代码片段,我在其中尝试测试数据成员:
#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 主干,替换如预期的那样失败。
我猜这是通过 this bug report 解决的,根据别名模板(例如 is_data_member
)的参数,如果它们出现在非类型模板的类型说明符中,则在替换期间未被正确处理参数.