是否可以将std::is_invocable
与任意函数参数类型一起使用,例如:std::is_invocable<Function, auto>
。这个想法是检查Function
是否可以接受1个参数,而不管参数的类型如何。对于一个用例,请考虑两个lambda:auto lambda1 = [](auto x) {...}
,auto lambda2 = [](auto x, auto y) {...}
和一个更高阶的模板化函数:
// specialize for 1 argument
template<typename Function, std::enable_if_t<(std::is_invocable<Function, auto>::value && !std::is_invocable<Function, auto, auto>::value)>, bool> = true>
void higherOrderFunc(Function&& func);
// specialize for 2 arguments
template<typename Function, std::enable_if_t<std::is_invocable<Function, auto, auto>::value, bool> = true>
void higherOrderFunc(Function&& func);
第一种情况下的!std::is_invocable<Function, auto, auto>::value
是为了防止重载函数产生歧义(也就是说,在这种情况下,首选的专业化将是歧义的2个参数)。
请注意,我知道在这种情况下不能像这样使用auto
。我在问是否有办法(至少部分地)实现这种行为。
答案 0 :(得分:2)
也许不是一个完美的解决方案...但是您可以尝试使用passepartout
struct passepartout
{
template <typename T>
operator T & ();
template <typename T>
operator T && ();
};
观察到仅声明转换运算符,未定义;因此该结构可以在decltype()
和std::declval()
(以及std::is_invocable
)中使用,但无法实例化。
现在,您可以将higherOrderFunc
的{{1}}传递引用写入passepartout
。
std::is_invocable
诀窍在于,如果可调用对象等待template <typename F,
std::enable_if_t<
std::is_invocable_v<F, passepartout &>
&& ! std::is_invocable_v<F, passepartout &, passepartout &>, bool>
= true>
void higherOrderFunc (F)
{ std::cout << "-- one parameter callable" << std::endl; }
template <typename F,
std::enable_if_t<
std::is_invocable_v<F, passepartout &, passepartout &>, bool> = true>
void higherOrderFunc (F)
{ std::cout << "-- two parameter callable" << std::endl; }
(或auto
或auto &
),则类型推导为auto &&
本身;当可调用等待特定类型(在以下示例中为passepartout
,带有或不带有引用)时,模板int
(根据情况为operator T & ()
)在某种意义上是兼容的)与预期的类型。
以下是完整的编译示例
operator T && ()