gpt4 book ai didi

c++ - 具有任意函数参数类型的 is_invocable

转载 作者:行者123 更新时间:2023-11-30 03:15:37 29 4
gpt4 key购买 nike

有没有办法使用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在这种情况下不能这样使用。我在问是否有办法(至少部分地)实现这种行为。

最佳答案

也许不是一个完美的解决方案...但您可以尝试使用 passepartout

struct passepartout
{
template <typename T>
operator T & ();

template <typename T>
operator T && ();
};

注意转换运算符只是声明的,没有定义;所以这个结构可以在 decltype()std::declval() (和 std::is_invocable)中使用,但不能被实例化。

现在您可以编写您的 higherOrderFunc 将对 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 &&),则类型被推断为 路路通本身;当可调用等待特定类型(int,有或没有引用,在下面的示例中)时,模板 operator T & ()(或 operator T && (),根据情况)与预期类型兼容(在某种意义上)。

下面是一个完整的编译示例

#include <type_traits>
#include <iostream>

struct passepartout
{
template <typename T>
operator T & ();

template <typename T>
operator T && ();
};

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; }

int main ()
{
auto l1a = [](auto &&){};
auto l1b = [](int &){};
auto l2a = [](auto &, int &&){};
auto l2b = [](auto, int const &){};
auto l2c = [](auto &&, auto const &){};
auto l2d = [](int &&, auto const &, auto && ...){};

higherOrderFunc(l1a);
higherOrderFunc(l1b);
higherOrderFunc(l2a);
higherOrderFunc(l2b);
higherOrderFunc(l2c);
higherOrderFunc(l2c);
higherOrderFunc(l2d);
}

关于c++ - 具有任意函数参数类型的 is_invocable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56913266/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com