如何确定 std::function 的参数数量?

2024-05-17

我有以下问题。假设您想编写一个可以采用 lambda 表达式的通用函数。我知道如果参数是 std::function 类型,那么我不仅可以使用 lambda,还可以使用函数,甚至可以使用函数指针。所以第一步,我做了以下事情:

void print(std::function<void(int, int)> fn) {
  fn(1,2);
}

int main() {

  print([](int i, int j) { std::cout << j <<','<<i<<'\n'; });
  return 0;
}

现在的问题是我想让这个函数变得通用,这意味着我不希望 lambda 表达式只有两个参数。 所以我尝试将打印函数的签名更改为更通用的签名,例如:

template <class function_type>
void print(function_type fn);

但现在的问题是该函数接受任何对象,而我对此不满意。 但主要问题是,我不知道对象 fn 可以接受多少个参数。

因此,在某种程度上,我正在寻找一种编译时方法来确定 fn 有多少个参数,并且如果可能的话将 fn 的类型更改为 std::function 。然后,鉴于我知道 fn 接受的参数数量,是否有一种通用方法来打包要传递给 fn 的任意数量的参数?我什至不知道这在 C++11 中是否可行。我的意思是,给定参数数量,有没有办法打包参数传递给 fn ?因此,如果有两个参数,那么我会调用

fn(arg1, arg2);

如果有三个:

fn(arg1, arg2, arg3);

等等。

感谢大家的见解。

aa


以下片段可能有用。

这给出了参数的数量std::function takes

template <typename Signature>
struct count_args;

template <typename Ret, typename... Args>
struct count_args<std::function<Ret(Args...)>> {
    static constexpr size_t value = sizeof...(Args);
};

例如,编译以下代码(clang 3.2、gcc 4.7.2 和 icc 13.1.0)

static_assert(count_args<std::function<void()        >>::value == 0, "Ops!");
static_assert(count_args<std::function<void(int)     >>::value == 1, "Ops!");
static_assert(count_args<std::function<void(int, int)>>::value == 2, "Ops!");

据我了解,您想要调用传递正确数量的参数的函数对象,对吗?然后,对于每个参数,我们需要提供一个可转换为其类型的值。具有这种普遍性的解决方案是非常困难的(甚至是不可能的)。因此,我将提出两种选择。

1每个参数都是其类型的值初始化对象。 (这是什么ecatmur https://stackoverflow.com/users/567292/ecatmur 建议 https://stackoverflow.com/a/15807558/1137388.)

template <typename Ret, typename... Args>
Ret call(const std::function<Ret(Args...)>& f) {
    return f(Args{}...); // for the intel compiler replace {} with ()
}

2给出一个固定值,所有参数都从该值隐式初始化:

template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<sizeof...(Args) == sizeof...(Vals), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val&, const Vals&... vals) {
    return f(vals...);
}

template <typename Ret, typename... Args, typename Val, typename... Vals>
typename std::enable_if<(sizeof...(Args) > sizeof...(Vals)), Ret>::type
call(const std::function<Ret(Args...)>& f, const Val& val, const Vals&... vals) {
    return call(f, val, val, vals...);
}

这三个重载是明确的,可以按以下示例所示使用:

{
    std::function<char()> f = []() -> char {
        std::cout << "f() ";
        return 'A';
    };
    std::cout << call(f)    << std::endl; // calls f()
    std::cout << call(f, 0) << std::endl; // calls f()
}
{
    std::function<char(int)> f = [](int i) -> char {
        std::cout << "f(" << i << ") ";
        return 'B';
    };
    std::cout << call(f)    << std::endl; // calls f(0)
    std::cout << call(f, 1) << std::endl; // calls f(1)
}
{
    std::function<char(int, int)> f = [](int i, int j) -> char {
        std::cout << "f(" << i << "," << j << ") ";
        return 'C';
    };
    std::cout << call(f)    << std::endl; // calls f(0, 0)
    std::cout << call(f, 2) << std::endl; // calls f(2, 2)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何确定 std::function 的参数数量? 的相关文章

随机推荐

  • 为什么反射搜索会突然找不到任何东西?

    我根据这个问题的答案有以下代码如何获取 ASP NET C 中请求的文件的 MIME 类型 https stackoverflow com questions 1302264 how do i get the mime type of a
  • 如何使用 PowerShell 扩展 ZIP 存档(UTF-8 文件名)

    我的 zip 存档有一个文件 P re No l txt 该 zip 可以通过 Windows 文件资源管理器 7 Zip 或我尝试过的任何其他工具很好地扩展 但我不知道如何从 PowerShell 中做到这一点 显然我已经尝试过展开 存档
  • Extbase - 从查询中获取创建的sql

    我想从我的typo3 扩展中获取一些数据库表 该扩展基于 extbase 查询总是不返回任何内容 但数据存在 我试过这个 query this gt createQuery query gt statement SELECT FROM my
  • C# 转换为小数

    如果有的话 有什么区别 decimal d decimal myDouble decimal d new decimal myDouble decimal d Convert ToDecimal myDouble 没有区别 如果你看一下源码
  • 当与“<”或“>”运算符一起使用时,MySQL 不使用 DATE 上的索引吗?

    我正在使用解释来测试这些查询 col 类型是 DATE 这使用索引 explain SELECT events FROM events WHERE events date 2010 06 11 这不 explain SELECT event
  • 使用 Python Mechanize 与 Flash 交互

    我正在尝试用 Python 创建一个处理 Flash 的自动化程序 现在我正在使用Python Mechanize 它非常适合填写表格 但是当涉及到flash时我不知道该怎么办 有谁知道我如何通过 Python mechanize 或其他一
  • 为什么 Double.TryParse() 对于包含 double.MaxValue 或 double.MinValue 的字符串返回 false?

    我有一个静态方法 它接受一个字符串作为输入 如果该字符串代表一个数字 则返回原始输入字符串 如果字符串不代表数字 则处理输入字符串并返回转换后的字符串 我正在写测试用例 我正在尝试验证包含以下任一内容的输入字符串double MinValu
  • JavaFX ReadOnlyListProperty 不是只读的?

    这段代码抛出 UnsupportedOperationException 正如我所期望的那样 因为它是只读的 ListProperty
  • 如何在文件系统中存储图像

    目前 我已将图像 最大 6MB 作为 BLOB 存储在 InnoDB 表中 随着数据大小的增长 夜间备份变得越来越慢 阻碍了正常性能 因此 二进制数据需要进入文件系统 指向文件的指针将保存在数据库中 数据具有树状关系 main site u
  • QT从QTableWidgetItem继承到Widget并覆盖'<'运算符

    我想要一个QTableWidget具有定制的某些单元QProgressBars 并且我希望能够对包含这些的列进行排序 我的定制QProgressBar继承自两者QProgressBar and QTableWidgetItem 并且我正在覆
  • 使用 setAttribute() 添加“onclick”函数

    为什么以下不起作用 显然该功能尚未添加 function activatetypeinput event devtype The function is called but it doesn t set the attribute var
  • 在Python中切片以反转列表的一部分

    我有一个列表 我想从后到尾提取其中的子切片 用两行代码 这是 mylist mysublist mylist begin end mysublist mysublist 1 是否有切片符号可以在一行中获得相同的效果 这 mysublist
  • 从 java sdk 向对等方发送提案时出现访问被拒绝错误

    我正在尝试使用以下代码查询区块链并收到访问被拒绝错误 我也遇到同样的错误sendTransactionProposal方法也是如此 UserContext adminUserContext RegisterEnrollUser regist
  • 如何从迭代器推导连续内存

    不知何故 本土stl copy VC Dinkumware 上的算法表明它可以使用memcpy 可以轻松复制的数据 一个凡人能做到这一点吗 假设每个元素都是普通可复制的 random access iterator 是否意味着连续内存 标准
  • django AuditTrail 与还原

    我正在开发一个新的网络应用程序 我需要将数据库中的任何更改存储到审核表中 此类审计表的目的是 稍后在真正的物理审计中 我们可以确定在某种情况下发生了什么 谁编辑了什么以及数据库当时的状态是什么 复杂的计算 所以大多数审计表将被写入而不是读取
  • 如何将 int[] 转换为 uint8[]

    所以 我需要你的帮助 我找不到关于该主题的任何内容 Golang 是一门刚刚诞生的语言 所以对于像我这样的新手来说很难快速找到答案 预先声明的 Goint类型大小是特定于实现的 32 位或 64 位 数字类型 http golang org
  • AppCompat v21 工具栏更改徽标大小

    我正在从以前的操作栏迁移到 appcompat v21 中的新工具栏功能 我仍然想将徽标保留在操作栏 工具栏 的左上角 为此 我在布局中添加了支持工具栏 并为其创建了一个新的工具栏 app theme style NewToolBarSty
  • 如何重新定位或移动 Google Maps SDK 上的当前位置按钮?

    如何将 Objective C 中的当前位置按钮移至我的偏好 现在 我已启用它 但底角有东西挡住了它 Thanks 您可以使用 padding 将按钮向上移动 self mapView padding UIEdgeInsets top 0
  • 使用 posix shell 测试字符串中的正则表达式

    如何测试字符串是否与特定字符串匹配正则表达式与基本 无 bash 或任何其他 posix shell 脚本 在 if 语句中 您可以使用expr在 POSIX shell 中计算正则表达式的命令 s Abc expr s alpha 3 e
  • 如何确定 std::function 的参数数量?

    我有以下问题 假设您想编写一个可以采用 lambda 表达式的通用函数 我知道如果参数是 std function 类型 那么我不仅可以使用 lambda 还可以使用函数 甚至可以使用函数指针 所以第一步 我做了以下事情 void prin