如何使用 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/