c++ - 检查类是否可流式传输的概念

标签 c++ c++-concepts

如何使用 std::ostream 实现一个概念来检查类型是否可流式传输?可能使用约束/requires ,但我通过谷歌找到的信息要么非常基本,要么也可以是克林贡语。

template<typename T> concept bool can_ostream()
{
    return check_if_operator<<(..)_is_in_T;  or something like this
}

所以我可以使用它,例如:
template<can_ostream T> struct X { ... }

最佳答案

概念非常新。我大约 90% 确定以下是执行此操作的正确方法,但我无法让它在 clang 上编译:

template <typename T>
concept Streamable = 
  requires(std::ostream &os, T value) {
    { os << value } -> std::convertible_to<std::ostream &>;
  };

要绕过 clang 的限制,您可以这样做:
template <typename T>
concept Stream = std::is_convertible_v<T, std::ostream &>;

template <typename T>
concept Streamable =
  requires(std::ostream &os, T value) {
    { os << value } -> Stream;
  };

另一种方法是在没有概念的情况下定义特征,然后根据特征定义概念。但是,您牺牲了概念的好处之一,即错误消息。
// This is how we used to do things back in my day

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

template <typename T>
struct is_streamable<T, std::enable_if_t<
  std::is_convertible_v<
    decltype(std::declval<std::ostream &>() << std::declval<T>()),
    std::ostream &
  >
>> : std::true_type {};

template <typename T>
concept Streamable = is_streamable<T>::value;

对于不支持概念的编译器,你可以使用 is_streamable特征。上面的定义是 C++17,但经过一些调整,这可以在 C++11 中完成。
template <typename T, typename = void>
struct is_streamable : std::false_type {};

template <typename T>
struct is_streamable<T, typename std::enable_if<
  std::is_convertible<
    decltype(std::declval<std::ostream &>() << std::declval<T>()),
    std::ostream &
  >::value
>::type> : std::true_type {};

概念只是糖。 概念为您提供更好的错误消息,并且它们比上面的模板内容更容易编写。 AFAIK,他们不允许你做任何你在 C++17 中无法做的事情。

我意识到可以稍微简化这个特征。我再次使用 C++11 来保持可移植性。
template <typename T, typename = void>
struct is_streamable : std::false_type {};

template <typename T>
struct is_streamable<T, decltype(
  static_cast<std::ostream &>(std::declval<std::ostream &>() << std::declval<T>())
)> : std::true_type {};

由于我再次编​​辑答案,我会说概念只是糖! C++20 是一个很大的。还需要一段时间才能获得足够广泛的支持,才能在生产中使用概念。

关于c++ - 检查类是否可流式传输的概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61199610/

相关文章:

c++ - 模板类成员函数的完美转发返回类型

c++ - 顺时针旋转 2D 矩阵时简化代码以避免 TLE

c++ - 以下小于(<)运算符对于什么类型 T 是合法的?

c++ - 我们可以声明一个结构体符合一个概念吗?

C++ TS 概念和访问器

C++ 通过引用传递 : two level deep function calls

c++ - 没有 typedef 的运算符 member_function_pointer_type()?

c++ - 如何在 C++ 程序中使用下标数字?

c++ - 编译器选择了错误的重载函数

c++ - 根据类型检查概念