c++ - 检查类是否可流式传输的概念
问题描述
如何实现一个概念来检查一个类型是否可以使用 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
trait。上面的定义是 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 是一个大的。要得到足够广泛的支持以使在生产中使用概念变得可行还需要一段时间。
推荐阅读
- html - 未以所需方式显示的答案
- angular - Angular 6 错误:JSONP 注入脚本未调用回调
- javascript - Chrome 浏览器控制台 javascript 参考
- javascript - HTML 输入 EventListener - 取消选择
- x10 - 在 x10 中调用此排序功能的正确方法是什么?
- javascript - 当路径始终转换为 url 时,如何使用脚本标记将 npm 包的链接添加到 django 模板
- python - 通过 conda 安装 tensorflow 失败
- python-3.x - 如何在opencv python中显示没有标题栏和边框的图像
- javascript - 设置一个 cookie 以显示一次性模式弹出而不调用任何 JavaScript 库 - 仅限本机 JavaScript/DOM API
- python - 使用 PIL `Image.fromarray` 创建图像导致 AttributeError: 'list' object has no attribute '__array_interface__'