完美穿越

2024-04-07

我正在考虑一个与完美转发有一些相似之处的问题,但是函数参数没有传递给被调用的函数,而是返回了。这就是为什么我称之为“完美传递”。

问题如下:

假设我们有一个函数,它通过引用(可能还有一些额外的参数)获取一个对象,修改该对象,然后返回修改后的对象。此类函数最著名的示例可能是operator<< and operator>>对于 iostream。

让我们使用 iostreams 作为例子,因为它可以很好地展示我所追求的内容。例如,人们有时想做的一件事是:

std::string s = (std::ostringstream() << foo << bar << baz).str();

当然这是行不通的,原因有二:

  • std::ostringstream()是一个右值,但是operator<<将左值作为第一个参数

  • operator<<返回一个ostream&(好吧,至少对于标准的实际上是basic_ostream<CharT, Traits>& where CharT and Traits从第一个参数推导出来)。

因此,假设我们要设计插入运算符,以便上述工作正常进行(显然您不能对现有运算符执行此操作,但可以对您自己的类执行此操作)。显然,该解决方案应具有以下特征:

  • 第一个参数可以接受左值或右值。

  • 返回类型应该与传入的类型相同。但是当然它仍然应该只接受ostreams(即从实例化派生的类)basic_ostream).

虽然在这个特定的用例中不需要它,但我想添加第三个要求:

  • 如果第一个参数是右值,则返回值也是右值,否则返回左值。

这个额外的规则是为了让你可以从通过函数传递的右值进行移动构造(我不知道 C++11 流是否可移动构造,但它旨在成为一个更通用的方案,流就像方便的例子)。

显然,在C++03中,这些要求并不能全部满足。然而,在 C++11 中,我们有右值引用,这应该使这成为可能。

这是我的尝试:

#include <iostream>
#include <sstream>
#include <string>

template<typename Ostream> struct is_ostream
{
  typedef typename std::remove_reference<Ostream>::type candidate;
  typedef typename candidate::char_type char_type;
  typedef typename candidate::traits_type traits_type;
  typedef std::basic_ostream<char_type, traits_type> basic_ostream;
  static const bool value = std::is_base_of<basic_ostream, candidate>::value;
};

class SomeType {};

template<typename Ostream>
 typename std::enable_if<is_ostream<Ostream>::value, Ostream&&>::type
  operator<<(Ostream&& is, SomeType const& x)
{
  is << "SomeType";
  return std::forward<Ostream>(is);
}

int main()
{
  SomeType t;

  std::string s = (std::ostringstream() << t).str();

  std::cout << s << std::endl;
}

它确实是用 gcc 编译的(使用选项-std=c++0x),运行时输出SomeType正如预期的那样。然而,到达那里是一个相当复杂的机制。

因此我的问题是:

  1. 我编写的输出运算符是否确实按预期工作(并满足我给出的所有要求)?或者它会以意想不到的方式失败或产生其他意想不到的后果吗?特别是:我使用的是std::forward这里正确吗?

  2. 有没有更简单的方法来满足要求?

  3. 假设这确实是正确的并且是最简单的方法:您认为这样做是个好主意吗?还是您会建议反对它(既专门针对我的示例中的流输出,又作为传递对象的更通用方案)通过函数)?


std::ostringstream()是一个右值,但是operator<<取一个左值 作为第一个参数

有一个通用插入器来获取右值流,但它返回一个basic_ostream<charT, traits>&:

template <class charT, class traits, class T>
  basic_ostream<charT, traits>&
  operator<<(basic_ostream<charT, traits>&& os, const T& x);

为了在您的示例中正常工作,它必须返回流的派生类型(std::ostringstram).

  1. 我编写的输出运算符是否确实按预期工作(并满足我给出的所有要求)?或者它可能会失败 意想不到的方式或有其他意想不到的后果?特别是:是 我的使用std::forward这里正确吗?

你的代码对我来说看起来是正确的。

  1. 有没有更简单的方法来满足要求?

您的代码看起来与我为解决此问题而编写的代码类似(见下文)。

  1. 假设这确实是正确的并且是最简单的方法:您认为这样做是个好主意吗?或者您会建议反对吗 (都专门用于流输出,如我的示例中所示,以及更多 通过函数传递对象的一般方案)?

这个习语对我来说看起来不错。

In libc++ http://libcxx.llvm.org/我定义了右值 ostream 插入器,如下所示(作为扩展)。我试图使其标准化,但已经晚了,可以理解的是,委员会没有心情进行更多的讨论:

template <class _Stream, class _Tp>
inline
typename enable_if
<
    !is_lvalue_reference<_Stream>::value &&
    is_base_of<ios_base, _Stream>::value,
    _Stream&&
>::type
operator<<(_Stream&& __os, const _Tp& __x)
{
    __os << __x;
    return std::move(__os);
}

与你不同的是,这个only接受右值流。但与您的一样,它返回具体的派生类型,因此适用于您的示例。

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

完美穿越 的相关文章

  • 将处理后的图形绘制到另一个图形中

    我想将一个经过处理的图形绘制到另一个图形中 I have two graphics var gHead Graphics FromImage h var gBackground Graphics FromImage b Transform
  • Mono 无法保存用户设置

    我在 Mono Ubuntu 上保存用户设置时遇到问题 这是代码示例 private void Form1 Load object sender EventArgs e string savedText Properties Setting
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • 在 C++11 中省略返回类型

    我最近发现自己在 C 11 模式下的 gcc 4 5 中使用了以下宏 define RETURN x gt decltype x return x 并编写这样的函数 template
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • 如何用 kevent() 替换 select() 以获得更高的性能?

    来自Kqueue 维基百科页面 http en wikipedia org wiki Kqueue Kqueue 在内核和用户空间之间提供高效的输入和输出事件管道 因此 可以修改事件过滤器以及接收待处理事件 同时每次主事件循环迭代仅使用对
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • Xamarin Android:获取内存中的所有进程

    有没有办法读取所有进程 而不仅仅是正在运行的进程 如果我对 Android 的理解正确的话 一次只有一个进程在运行 其他所有进程都被冻结 后台进程被忽略 您可以使用以下代码片段获取当前正在运行的所有 Android 应用程序进程 Activ
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • gdb 在 docker 上立即退出“进程已完成,退出代码 1”或 lldb“数据包返回错误 8”。另外:如何在 docker 中允许进行 C++ 调试

    这花了我一整天的时间才找到 所以我将其发布以供将来参考 我正在 docker 镜像上开发 C 我正在使用克利翁 我的代码是在调试模式下编译的 并且在运行模式下运行良好 但是当尝试调试时 进程会立即退出 并显示非常丰富的信息 Process
  • 范围和临时初始化列表

    我试图将我认为是纯右值的内容传递到范围适配器闭包对象中 除非我将名称绑定到初始值设定项列表并使其成为左值 否则它不会编译 这里发生了什么 include
  • 通过不同 DLL 或 EXE 中的指针或引用访问 STL 对象时发生访问冲突

    我在使用旧版 VC6 时遇到以下问题 我只是无法切换到现代编译器 因为我正在处理遗留代码库 http support microsoft com kb 172396 http support microsoft com kb 172396
  • 如何排列表格中的项目 - MVC3 视图 (Index.cshtml)

    我想使用 ASP NET MVC3 显示特定类型食品样本中存在的不同类型维生素的含量 如何在我的视图 Index cshtml 中显示它 an example 这些是我的代码 table tr th th foreach var m in
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • Silverlight Datagrid:在对列进行排序时突出显示整个列

    我的 Silverlight 应用程序中有一个 DataGrid 我想在对该列进行排序时突出显示整个列 它在概念上与上一个问题类似 Silverlight DataGrid 突出显示整列 https stackoverflow com qu
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS

随机推荐

  • 在 NumPy 数组中查找等于 0 的元素索引

    NumPy 具有高效的函数 方法nonzero http docs scipy org doc numpy reference generated numpy nonzero html识别非零元素的索引ndarray目的 获取元素索引的最有
  • 如何使用 WorkManager 安排通知?

    我想在每次用户在数据库中添加特定时间的注释时安排通知 虽然使用 AlarmManager BroadcastReceiver 等有多种方法可以做到这一点 但如何使用 WorkManager 来完成呢 WorkManager不适合需要在特定时
  • Bootstrap 3.0 和 Google 地图 javascript API V3 样式

    我正在尝试将谷歌地图 javascript API v3 实现到利用 Bootstrap 3 0 轮播 基本主题的 Bootstrap 3 0 网站中 问题是 div div 如果我尝试将其包含在任何其他 div 或 bootstrap 3
  • 如何使用 RTTI 区分 TDateTime 属性和 Double 属性?

    使用Delphi 2010中的RTTI系统 有什么方法可以找出属性是否是TDateTime 目前 每当我回调 asVariant 以及检查属性类型时 它都会将其视为双精度 这是因为它只能看到基本类型吗 TDateTime 双精度 尝试检查N
  • 如何正确使用AddBatch/withBatch将xml标签值批量插入数据库表

    innerXml 是一个带有大量 xml 标签的 xml 文件 我正在尝试获取标签值并将它们转储到数据库表中 我已经尝试过下面的代码 它工作正常 innerXml Row each Row gt sql execute INSERT INT
  • adb 已停止在 android studio 中工作

    我正在尝试在 android studio 中构建我的第一个应用程序并收到错误 adb exe 已停止工作 我正在Windows xp 32位系统上工作 Have tried several solutions available onli
  • 如何更新 JRuby 的 gem 命令?

    我们如何更新 JRuby 使用的 gem 版本 JRuby 使用 gem 1 5 1 我们希望将其升级到 1 8 7 我们希望将 gems 安装在 Ruby gems 中 We run bin jruby gem install rubyg
  • NuGet:远程服务器返回错误(403)禁止

    每当我尝试安装软件包时 我都会收到此错误 remote server returned an Error 403 Forbidden 我可以使用其他命令 例如 get package ListAvailable 并发现已安装的软件包是否有任
  • 在部署之前使用 local :path 检查 gems

    对于某些 Rails 应用程序 我希望在部署时有一个安全防护措施 以检查是否有一些 gem 配置为在本地路径中查找 一些上下文可能有助于理解 当我处于开发模式时 我希望在 本地模式 下有一个 gem 在我的Gemfile它的配置如下 gem
  • Node fs 复制文件夹

    我正在尝试使用 Node 复制文件夹fs模块 我熟悉readFileSync and writeFileSync 方法 但我想知道应该使用什么方法来复制指定的文件夹 您可以使用fs extra https www npmjs com pac
  • 无法读取文本框值

    我在 AjaxFileUpload1 的 pageupload 事件期间将页面上的文本框的值分配给变量 问题是 即使没有错误抛出 我也没有从文本框获取值到我的变量 我的变量是 string scn txtSCN Text string li
  • CodeIgniter 验证变量/输入不是来自表单?

    假设我有用户生成的数据 这些数据不是通过表单发布的 有没有办法可以使用 扩展 CodeIgnitors form validation 类来验证该数据 eg 是的 您可以通过set data
  • 将一个整数平均分为 X 部分

    我正在 PHP 中寻找一种有效的方法来将数字等分 数字始终是整数 没有浮点数 假设我有一个数组 hours 其值从 1 到 24 hours 1 等 和一个包含整数的变量 int 我想要实现的是将 int 的值平均分为 24 个部分 这样我
  • 标签中的 Ember 车把模板

    ember 特别是应用程序模板 是否可以在 head 标签内进行操作 以便动态更改标题标签 元标签 外部 css 样式表和 favicon 等内容 如果是这样 那么一种干净的方法是什么 为了完成这项工作 我所做的是创建车把助手 例如 如果您
  • 保存用户个人资料详细信息 Android 应用程序的最佳方式

    我正在创建一个有多个用户的应用程序 我创建了一个对象 用户 其中包含更多详细信息 姓名 年龄 自定义对象等 因为我有一个自定义对象 所以我知道使用共享首选项会很困难 存储用户数据的最佳方式是什么 我研究过 SQLite 但找不到将自定义对象
  • 有没有办法从应用程序脚本中的 graphql API 获取数据?

    我正在尝试通过应用程序脚本从 graphql API 获取数据 使用 POST 获取 graphql 数据有一个问题 提供从 GraphQL API 获取的查询字符串 https stackoverflow com questions 47
  • C++ 模板复制构造函数,编译器说“传递 const 作为此参数丢弃限定符”

    我正在尝试创建动态矩阵的模板类 以我目前对 C 的了解 我设法解决了一些问题 但我陷入了复制构造函数和重载运算符 的困境 换句话说 我无法创建我的对象的副本 在我看来 这应该可行 但我的朋友编译器告诉我 我有 1 个错误 错误 将 cons
  • 如何排查/解决 Xcode 10.1/iOS 12.1 中出现的“信号强度查询返回错误”日志?

    最近更新到 iOS 12 1 从 12 0 开始 Xcode 10 1 从 10 0 开始 在我的物理设备上进行调试时 在 Xcode 控制台中看到大量错误消息 如下所示 NetworkInfo Signal strength query
  • 客户端Web - 如何随时获取当前记录ID

    我正在努力 基于工作流程状态的不同权限 https stackoverflow com questions 10994216 different permissions based on workflow state问题 但我正在努力解决这
  • 完美穿越

    我正在考虑一个与完美转发有一些相似之处的问题 但是函数参数没有传递给被调用的函数 而是返回了 这就是为什么我称之为 完美传递 问题如下 假设我们有一个函数 它通过引用 可能还有一些额外的参数 获取一个对象 修改该对象 然后返回修改后的对象