用 C++ 20 个概念实现 std::is_invocable_r
Implementing std::is_invocable_r with C++ 20 concepts
我正在尝试使用 C++ 20 的概念实现 std::is_invocable<R, Callable, Args...>
,尽可能少地使用 STL 的帮助,并且不使用 std::invoke
等
这是我目前的做法。虽然它会导致编译错误(msvc):
error C3864: 'is_invocable_r': requires clause is incompatible with the declaration
template<class R, class Fn, class... ArgTypes>
requires requires(Fn fn, ArgTypes... arg_types)
{
{ std::forward<Fn>(fn)(std::forward<ArgTypes>(arg_types)...) } -> std::same_as<R>;
}
struct is_invocable_r : std::true_type {};
template<class R, class Fn, class... ArgTypes>
struct is_invocable_r : std::false_type {};
这样做的正确方法是什么?
两个问题。
- 您没有专门化模板。您正在重新声明它。必须使用模板 ID 声明部分特化。 IE。
is_invocable_r<...>
.
- 部分特化应该比主模板声明更多约束,而不是更少。而且它必须是主要参数方面的更特殊情况;我们不能只是重复完全相同的参数列表并将其称为特化。
考虑到这一点,定义特征的更简单方法可能是:
template<class R, class Fn, class... ArgTypes>
struct is_invocable_r :
std::bool_constant<
requires(Fn fn, ArgTypes... arg_types)
{
{ std::forward<Fn>(fn)(std::forward<ArgTypes>(arg_types)...) } -> std::same_as<R>;
}
>
{};
由于必须显式提供所有模板参数,并且没有空间专门化您的 class 模板(不能在 class 模板中的参数包后添加参数),我们根本无法专精。
相反,我们只是将 requires
表达式的结果输入 bool_constant
,因为它是最终决定特征值的表达式的结果1.
1 - 您的 requires 表达式不包含指向成员的指针,因此它不等同于 std::is_invocable_r
给出的结果。需要更多的改进(甚至可能通过专业化)来涵盖这种情况。
我正在尝试使用 C++ 20 的概念实现 std::is_invocable<R, Callable, Args...>
,尽可能少地使用 STL 的帮助,并且不使用 std::invoke
等
这是我目前的做法。虽然它会导致编译错误(msvc):
error C3864: 'is_invocable_r': requires clause is incompatible with the declaration
template<class R, class Fn, class... ArgTypes>
requires requires(Fn fn, ArgTypes... arg_types)
{
{ std::forward<Fn>(fn)(std::forward<ArgTypes>(arg_types)...) } -> std::same_as<R>;
}
struct is_invocable_r : std::true_type {};
template<class R, class Fn, class... ArgTypes>
struct is_invocable_r : std::false_type {};
这样做的正确方法是什么?
两个问题。
- 您没有专门化模板。您正在重新声明它。必须使用模板 ID 声明部分特化。 IE。
is_invocable_r<...>
. - 部分特化应该比主模板声明更多约束,而不是更少。而且它必须是主要参数方面的更特殊情况;我们不能只是重复完全相同的参数列表并将其称为特化。
考虑到这一点,定义特征的更简单方法可能是:
template<class R, class Fn, class... ArgTypes>
struct is_invocable_r :
std::bool_constant<
requires(Fn fn, ArgTypes... arg_types)
{
{ std::forward<Fn>(fn)(std::forward<ArgTypes>(arg_types)...) } -> std::same_as<R>;
}
>
{};
由于必须显式提供所有模板参数,并且没有空间专门化您的 class 模板(不能在 class 模板中的参数包后添加参数),我们根本无法专精。
相反,我们只是将 requires
表达式的结果输入 bool_constant
,因为它是最终决定特征值的表达式的结果1.
1 - 您的 requires 表达式不包含指向成员的指针,因此它不等同于 std::is_invocable_r
给出的结果。需要更多的改进(甚至可能通过专业化)来涵盖这种情况。