动态分派到模板函数 C++

2024-02-06

我有一个模板函数(在我的例子中是 cuda 内核),其中有少量布尔模板参数可以在运行时进行选择。我很高兴在编译时实例化所有排列并动态分派,如下所示(对于布尔值 b0,b1,b2):

if (b0) {
    if (b1) {
        if (b2) {
            myFunc<true,true,true,otherArgs>(args);
        } else {
            myFunc<true,true,false,otherArgs>(args);
        }
    } else {
        if(b2) {
            myFunc<true,false,true,otherArgs>(args);
        } else {
            myFunc<true,false,false,otherArgs>(args);
        }
    }
} else {
    if(b1) {
        if(b2) {
            myFunc<false,true,true,otherArgs>(args);
        } else {
            myFunc<false,true,false,otherArgs>(args);
        }
    } else {
        if(b2) {
            myFunc<false,false,true,otherArgs>(args);
        } else {
            myFunc<false,false,false,otherArgs>(args);
        }
    }
}

这写起来很烦人,如果我最终得到 b3 和 b4,情况会变得更加糟糕。

有没有一种简单的方法可以在 C++11/14 中以更简洁的方式重写它,而无需引入大型外部库(如 boost)?就像是:

const auto dispatcher = construct_dispatcher<bool, 3>(myFunc);

...

dispatcher(b0,b1,b2,otherArgs,args);

没问题。

template<bool b>
using kbool = std::integral_constant<bool, b>;

template<std::size_t max>
struct dispatch_bools {
  template<std::size_t N, class F, class...Bools>
  void operator()( std::array<bool, N> const& input, F&& continuation, Bools... )
  {
    if (input[max-1])
      dispatch_bools<max-1>{}( input, continuation, kbool<true>{}, Bools{}... );
    else
      dispatch_bools<max-1>{}( input, continuation, kbool<false>{}, Bools{}... );
  }
};
template<>
struct dispatch_bools<0> {
  template<std::size_t N, class F, class...Bools>
  void operator()( std::array<bool, N> const& input, F&& continuation, Bools... )
  {
     continuation( Bools{}... );
  }
};

实例 http://coliru.stacked-crooked.com/a/a7b8d1b13e41898e.

So kbool是一个变量,表示编译时常量布尔值。dispatch_bools是一个辅助结构体,它有一个operator().

This operator()需要一个运行时数组bools,并开始于max-1继续产生最大 if/else 分支,每个分支递归调用dispatch_bools又计算了一个编译时布尔值。

这会生成 2^max 代码;正是您不想编写的代码。

延续一直向下传递到底部递归(其中max=0)。此时,所有编译时布尔值都已构建完毕——我们称之为continuation::operator()将这些编译时布尔值作为函数参数传递。

希望continuation::operator()是一个可以接受编译时布尔值的模板函数。如果是,则有 2^max 个实例,每个实例都有 2^max 种可能的真/假组合。


要使用它来解决您的问题c++14 /questions/tagged/c%2b%2b14你只需这样做:

std::array<bool, 3> bargs={{b0, b1, b2}};
dispatch_bools<3>{}(bargs, [&](auto...Bargs){
  myFunc<decltype(Bargs)::value...,otherArgs>(args);
});

这很容易,因为c++14 /questions/tagged/c%2b%2b14 has auto拉姆达;它可以有一个模板operator()在 lambda 上。将这些编译时布尔参数转换回模板非类型参数很容易。

请注意,许多名义上c++11 /questions/tagged/c%2b%2b11编译器支持自动 lambda,因为它非常简单。但是,如果您缺少它,您仍然可以解决这个问题c++11 /questions/tagged/c%2b%2b11使用辅助结构:

template<class OtherArgs>
struct callMyFunc {
  Args args;
  template<class...Bools>
  void operator()(Bools...){
    myFunc<Bools::value...,otherArgs>(args);
  }
};

现在使用的是:

std::array<bool, 3> bargs={{b0, b1, b2}};
dispatch_bools<3>{}(bargs, callMyFunc<otherArgs>{args});

这基本上是手动编写的c++14 /questions/tagged/c%2b%2b14lambda 就可以了。


In c++14 /questions/tagged/c%2b%2b14你可以替换void with auto并返回而不只是递归,它会很好地为您推断出返回类型。

如果你想要这个功能c++11 /questions/tagged/c%2b%2b11你可以写很多decltype代码,或者你可以使用这个宏:

#define RETURNS(...) \
  noexcept(noexcept(__VA_ARGS__)) \
  -> decltype(__VA_ARGS__) \
  { return __VA_ARGS__; }

并写出正文dispatch_bools like:

template<class T, std::size_t N, class F, class...Bools>
auto operator()( std::array<T, N> const& input, F&& continuation, Bools... )
RETURNS(
 (input[max-1])?
    dispatch_bools<max-1>{}( input, continutation, kbool<true>{}, Bools{}... )
 :
    dispatch_bools<max-1>{}( input, continutation, kbool<false>{}, Bools{}... )
)

和类似的<0>专业化,并获得c++14 /questions/tagged/c%2b%2b14款式退货扣除c++11 /questions/tagged/c%2b%2b11.

RETURNS使得推断单行函数的返回类型变得微不足道。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态分派到模板函数 C++ 的相关文章

随机推荐

  • 多线程时 cv2 图像显示不起作用

    我试图在捕获网络摄像头时将图像显示在屏幕上 我使用的是 MAC 因此 我启动了两个线程 一个用于捕获视频 另一个用于在屏幕上呈现图像 webcam thread self init webcam thread images thread s
  • 从 setup.py 安装依赖项

    我想知道除了 deb 包之外 是否可以在我的 setup py 中配置我的包的依赖项 然后运行 sudo python setup py install 它们是自动安装的 已经在互联网上进行了研究 但我发现的一切都让我感到困惑 比如 req
  • 在 iOS Sprite Kit 游戏中创建关卡

    我正在创建一个游戏 我希望它有一个可以选择关卡的场景 然后有可以玩的关卡 我只是想知道当用户达到该级别时如何创建级别并保存 我正在考虑在 ViewController h 中创建一个 BOOL 并在每个场景中调用它 即 LevelCompl
  • 如何在 pytorch 中使用可学习参数,限制在 0 和 1 之间?

    我想使用一个仅取 0 到 1 之间值的可学习参数 我如何在 pytorch 中做到这一点 目前我正在使用 self beta Parameter torch Tensor 1 initialize zeros self beta 但当我训练
  • 无法删除 Solr 键

    从 Solr 文件集合中删除键时遇到问题 使用以下命令更新 Solr 集合
  • IP允许子目录访问NGINX

    我实际上使用 nginx 作为我的网络服务器 我试图使用以下命令拒绝所有子目录访问 location root usr share nginx html project index index html index htm index ph
  • 复合 if 语句更快,还是多个 if 语句更快?

    假设我们有两段代码 if foo True and bar False and baz True do something and if foo True if bar False if baz True do something 哪个更快
  • Eclipse 中的 Android 错误:“无法执行 dex:无法将新索引 65799 合并到非巨型指令中!”

    我正在尝试使用 Eclipse 使用 OpenSAML 的 Android 项目 我已在构建路径中添加了所有必需的 jar 文件 现在 当我将程序作为 Android 应用程序运行时 会出现以下错误 2012 11 18 11 52 59
  • 将 SHA-256 与 NodeJS 加密结合使用

    我正在尝试对 NodeJS 中的变量进行哈希处理 如下所示 var crypto require crypto var hash crypto createHash sha256 var code bacon code hash updat
  • 明显死锁 c3p0 0.9.5.1 弹簧

    我们在使用 c3p0 0 9 5 1 这是 c3p0 的最新版本 时面临明显的死锁 以下是我们正在使用的连接池配置 p driverClass app jdbc driverClassReplica p jdbcUrl jdbc mysql
  • EF7 在运行时更改连接字符串

    在 EF 的早期版本中 我们能够更改 dbcontext 连接字符串 如下所示 context Database Connection ConnectionString the new connectionstring 我们如何使用 EF7
  • 在 .Select lambda 中使用 async/await

    我正在使用 Asp Net Core Identity 并尝试简化一些投影用户列表的代码以及他们的角色到视图模型 这段代码可以工作 但是在试图简化它的过程中 我陷入了错误和好奇心的疯狂螺旋中 这是我的工作代码 var allUsers us
  • Selenium Chrome 驱动程序无法解析 getElementRegion 的值

    使用 chrome 驱动程序运行我的 selenium 测试时 我从 chrome 驱动程序中收到以下错误 测试在firefox下运行良好 未知错误 无法解析 getElementRegion 的值 这是代码 尝试单击提交按钮时失败 我正在
  • 将 UserControl 转换为自定义控件

    下面的 UserControl 效果很好 但我想让更改样式变得更容易 我尝试过的一件事是将其转换为自定义控件 但我停留在基础知识上 例如如何在处理属性更改的静态方法中设置工具提示 见下文 我尝试将样式移动到 ResourceDictiona
  • Qt formlayout 不垂直扩展 qplaintextedit

    我很困惑为什么Q纯文本编辑添加到窗口小部件时不会垂直调整大小QForm布局 在下面的代码中 文本字段可以正确地水平缩放 但不会垂直缩放 任何人都可以解释这种行为并提供解决方案吗 我已经尝试了所有我知道的技巧 但没有成功 from PyQt4
  • 操作导致超出Core配额限制。允许的最大数量:4,当前使用的数量:4,额外要求的数量:4。在 14 天免费试用期间

    我正在使用 14 天高级免费试用版 我正在尝试在 databricks 中创建并运行集群 我正在遵循快速入门指南 我如何收到以下错误 操作导致超出核心配额限制 允许的最大数量 4 当前使用的数量 4 额外请求的数量 4 我无法提高限制 因为
  • 在C中将格式化文件读取到char数组中

    我有一个非常简单的问题 我需要将文件的内容读入 C 中的字符数组中 该文件将始终格式化为两列字母 例如 A B B C E X C D 每个字母代表图形上的一个顶点 我稍后将处理它 我学习过使用 C 和 Java 进行编程 但我对 C 并不
  • JaCoCo:缺少类目录

    我对 JaCoCo 相当陌生 在生成代码覆盖率报告时遇到问题 这是我的项目结构 我的集成测试位于 integration tests 模块中 当我使用 mvn 构建项目时 我在日志记录中收到以下内容 INFO Skipping JaCoCo
  • 什么是重定向 URI?它如何应用于 OAuth2.0 的 iOS 应用程序?

    这里是初学者程序员 请原谅我的无知 解释会非常好 我尝试阅读某个 OAuth 2 0 服务的教程 但我不理解这个重定向 URI 在我的特定上下文中 假设我正在尝试构建一个使用 OAuth 2 0 进行某些服务的 iPhone 应用程序 我有
  • 动态分派到模板函数 C++

    我有一个模板函数 在我的例子中是 cuda 内核 其中有少量布尔模板参数可以在运行时进行选择 我很高兴在编译时实例化所有排列并动态分派 如下所示 对于布尔值 b0 b1 b2 if b0 if b1 if b2 myFunc