检查 class 是否可流式传输的概念
Concept to check if a class is streamable
我如何实现一个概念来检查类型是否可以使用 std::ostream 流式传输?可能使用约束/requires
,但我通过 google 找到的信息要么非常初级,要么也可以是克林贡语。
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 中不能做的事情。
我意识到可以稍微简化一下 trait。我再次使用 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 是一个大概念。还需要一段时间才能获得足够广泛的支持,以便在生产中使用概念。
您想要的概念的正确语法如下:
template <typename T>
concept Streamable = requires(std::ostream os, T value) {
{ os << value };
};
关于概念,clang 落后于 gcc。所以我推荐使用gcc。
You can run the following code online:
#include <iostream>
template <typename T>
concept Streamable = requires(std::ostream os, T value) {
{ os << value };
};
void call(Streamable auto obj)
{
std::ostream os(nullptr);
os.rdbuf(std::cout.rdbuf());
os << obj << std::endl;
//do stuff with os ...
}
int main()
{
call("Hi");
call(3.14159);
return 0;
}
.
我如何实现一个概念来检查类型是否可以使用 std::ostream 流式传输?可能使用约束/requires
,但我通过 google 找到的信息要么非常初级,要么也可以是克林贡语。
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 中不能做的事情。
我意识到可以稍微简化一下 trait。我再次使用 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 是一个大概念。还需要一段时间才能获得足够广泛的支持,以便在生产中使用概念。
您想要的概念的正确语法如下:
template <typename T>
concept Streamable = requires(std::ostream os, T value) {
{ os << value };
};
关于概念,clang 落后于 gcc。所以我推荐使用gcc。 You can run the following code online:
#include <iostream>
template <typename T>
concept Streamable = requires(std::ostream os, T value) {
{ os << value };
};
void call(Streamable auto obj)
{
std::ostream os(nullptr);
os.rdbuf(std::cout.rdbuf());
os << obj << std::endl;
//do stuff with os ...
}
int main()
{
call("Hi");
call(3.14159);
return 0;
}