我正在尝试使用 C++ 20 的概念在尽可能少的 STL 帮助下实现 std::is_invocable<R, Callable, Args...>
,并且不使用 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 {};
这样做的正确方法是什么?
答案 0 :(得分:2)
两个问题。
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>;
}
>
{};
由于必须明确提供所有模板参数,并且没有空间专门化您的类模板(不能在类模板中的参数包后添加参数),我们根本无法专门化。
相反,我们只是将 requires
表达式的结果提供给 bool_constant
,因为它是最终决定 trait1 值的表达式的结果。< /p>
1 - 您的 requires 表达式不包括指向成员的指针,因此它不等同于 std::is_invocable_r
给出的结果。需要更多细化(甚至可能通过专业化)来涵盖这种情况。