【问题标题】:Type trait to check if a type is readable from stream and MSVC类型特征以检查类型是否可从流和 MSVC 中读取
【发布时间】:2018-09-04 19:05:55
【问题描述】:

最近我遇到了the question 讨论的is_streamable 类型特征。所以我决定实现自己的版本并提出下一个解决方案来检查是否可以从std::istream 读取类型:

template<typename, typename = void>
struct is_readable_from_stream_impl
    : std::false_type {};

template<typename T>
struct is_readable_from_stream_impl<T, 
    std::void_t<decltype(std::declval<std::istream&>() >> std::declval<T>())>>
    : std::true_type {};

template<typename T>
struct is_readable_from_stream :
    is_readable_from_stream_impl<T> {};

template<typename T>
inline constexpr auto is_readable_from_stream_v = is_readable_from_stream<T>::value;

到目前为止,一切都很好。然后我添加了一个带有重载operator&gt;&gt;的自定义结构:

struct readable {};

std::istream& operator>>(std::istream& is, readable&)
{
    return is;
}

并测试了类型特征:

static_assert(is_readable_from_stream_v<readable&>);
static_assert(!is_readable_from_stream_v<readable>);

gcc 8.2clang 6.0.0 都通过了检查,但 MSVC rejects 是第二个断言。

我想知道我的实现(或测试)是否不正确,或者是 MSVC 的另一个问题。

【问题讨论】:

  • 该特征的名称不应该类似于“使用 >> 运算符从流中读取”吗?从流中读取还有很多其他方式。
  • @NeilButterworth 这是一个玩具示例,我实际上并不关心命名那么多......

标签: c++ typetraits


【解决方案1】:

这里的问题是 MSVS 可以将右值绑定到左值引用作为语言扩展。以下代码编译:

struct readable{ };

void foo(readable&)
{ }

void bar()
{
    foo(readable{});
}

使用可以使用/Za 选项(禁用语言扩展)来禁用它。然后你的断言将被传递。

【讨论】:

  • 啊,我想这是我第二次或第三次忘记这个美妙的扩展了。这是一个好点!
  • 如果可以的话,我建议使用/permissive-,而不仅仅是/Za。它使 MSVC 在许多它通常不这样做的地方符合标准。
  • 只是为了确认 - MSVS 启用右值到左值引用 右值到 const-lvalue-references(这是标准的)?
  • @Fureeish,是的,每个扩展的右值到左值引用,每个标准的右值到 const-lvalue-refs。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 2021-07-22
  • 2022-10-02
  • 2013-06-28
  • 1970-01-01
  • 2018-07-15
相关资源
最近更新 更多