草庐IT

c++ - 身份别名模板可以作为转发引用吗?

coder 2023-06-02 原文

考虑以下片段:

template <class T>
using identity = T;

template <class T>
void foo(identity<T>&&) {}

int main()
{
  int i{};
  foo(i);
}
i是左值,因此如果 foo声明一个转发引用参数,它应该编译。但是,如果 identity<T>&&变成int&& ,它应该会引发错误。

代码在 GCC 6.0.0 ( demo ) 中编译。

代码无法在 Clang 3.7.0 ( demo ) 中编译并显示错误消息:
error: no known conversion from 'int' 
to 'identity<int> &&' (aka 'int &&') for 1st argument

哪一个是对的?

最佳答案

考虑这个代码:

template<class T> using identity = T;

template<class T> void foo(identity<T>&&) { } //#1

template<class T> void foo(T&&) { } //#2

int main()
{
  int i{};
  foo(i);
}

GCC 和 Clang 都拒绝它,因为 #2是对 #1 的重新定义.如果它们实际上是相同的模板,我们可以期待 #1行为方式与 #2 完全相同, 意思是 identity<T>&&应该作为转发引用。按照这个逻辑,我们不知道哪个是对的,但 GCC 至少是一致的。

这也与标准 [14.5.7p2] 中的一个非常相似的示例一致。

我们还应该考虑模板参数推导在这种情况下的工作方式。如 identity是一个类模板,它的形式可以与函数参数的类型匹配而无需查看其定义,从而允许编译器推导出 T 的模板参数。 .但是,这里我们有一个别名模板; T不能推导出 intint&或其他任何东西,除非 identity<T>T 取代.否则,我们匹配什么?替换完成后,函数参数成为转发引用。

以上都支持identity<T>&&的想法(和 identity<T&&> )被视为等同于转发引用。

然而,似乎还有更多的东西,即用相应的类型 ID 立即替换别名模板 ID。第 [14.5.7p3] 段说:

However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id. [ Example:

template<typename...> using void_t = void; 
template<typename T> void_t<typename T::foo> f(); 
f<int>(); // error, int does not have a nested type foo 

—end example ]



这似乎与您的示例没有太大关系,但它实际上表明在某些情况下仍会考虑模板 ID 的初始形式,而与替换的类型 ID 无关。我想这开启了 identity<T>&& 的可能性。毕竟实际上不能被视为转发引用。

标准中似乎没有详细说明该区域。这表明处理类似问题的未解决问题的数量,在我看来都属于同一类别:在什么情况下,在实例化时应该考虑模板 ID 的初始形式,即使它应该被替换为遇到时立即对应的 type-id。查看问题 1980 , 20212025 .偶问题 14301554可以看作是处理类似的问题。

特别是issue 1980包含以下示例:
template<typename T, typename U> using X = T;
template<typename T> X<void, typename T::type> f();
template<typename T> X<void, typename T::other> f();

附注:

CWG felt that these two declarations should not be equivalent.



(CWG - 核心工作组)

类似的推理也适用于您的示例,即 identity<T>&&不等同于转发引用。这甚至可能具有实用值(value),作为一种直接的方法,当您只需要对推导的 T 的右值引用时,可以避免转发引用的贪婪。

所以,我认为你提出了一个非常有趣的问题。您的示例可能值得作为注释添加到 issue 1980 ,以确保在起草决议时考虑到这一点。

在我看来,你的问题的答案目前是一个响亮的“谁知道?”。

更新:在对其他相关的评论中,question , Piotr S.指出issue 1700 ,它被关闭为“不是缺陷”。它指的是该问题中描述的非常相似的案例,并包含以下基本原理:

Because the types of the function parameters are the same, regardless of whether written directly or via an alias template, deduction must be handled the same way in both cases.



我认为它也适用于这里讨论的案例,并暂时解决了这个问题:所有这些表格都应该被视为等同于转发引用。

(看看其他未决问题的决议是否间接改变了这一点会很有趣,但它们主要处理替代失败而不是其本身的推论,所以我猜这种间接影响是不太可能的。)

所有标准引用均针对当前工作草案 N4431,即最终 C++14 之后的第二个草案。

请注意,[14.5.7p3] 中的引用是最近添加的,在最终的 C++14 版本之后作为 DR1558 的分辨率包含在内。 .我认为随着其他问题以某种方式得到解决,我们可以期待在这方面有更多的补充。

在此之前,可能值得在 ISO C++ Standard - Discussion 中提出这个问题。团体;这应该引起合适的人的注意。

关于c++ - 身份别名模板可以作为转发引用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29851098/

有关c++ - 身份别名模板可以作为转发引用吗?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  4. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  7. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  8. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  9. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  10. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

随机推荐