【问题标题】:C++17 testing for data-member SFINAE: gcc vs clang数据成员 SFINAE 的 C++17 测试:gcc vs clang
【发布时间】: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&lt;...&gt; 语法,它就可以正常工作。
  • 顺便说一句。 is_data_member 不像您期望的那样工作。 decltype( std::declval&lt;B&gt;().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


【解决方案1】:

这似乎是 Clang 中的一个错误。使用当前的 Clang 主干,替换按预期失败。

我想这已经用this bug report 解决了,根据这些参数,如果别名模板(例如is_data_member)出现在非类型模板参数的类型说明符中,则在替换过程中不会正确处理它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 2018-03-29
    • 2015-11-12
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多